Skip to content

Commit

Permalink
feat(groups): Support creation of open groups
Browse files Browse the repository at this point in the history
We now allow creation of open groups, where non-owners can add members.
Removal is still only allowed for owner.

Fixes #386.
  • Loading branch information
zeenix committed Jan 8, 2024
1 parent 66f4769 commit db62e0c
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 65 deletions.
26 changes: 15 additions & 11 deletions extensions/warp-ipfs/examples/messenger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,8 @@ async fn main() -> anyhow::Result<()> {
writeln!(stdout, "{did} has been removed")?;

},
CreateGroupConversation(name, did_keys) => {
if let Err(e) = chat.create_group_conversation(Some(name.to_string()), did_keys).await {
CreateGroupConversation(name, did_keys, open) => {
if let Err(e) = chat.create_group_conversation(Some(name.to_string()), did_keys, open).await {
writeln!(stdout, "Error creating conversation: {e}")?;
continue
}
Expand Down Expand Up @@ -994,7 +994,7 @@ enum Command {
CreateConversation(DID),
AddRecipient(DID),
RemoveRecipient(DID),
CreateGroupConversation(String, Vec<DID>),
CreateGroupConversation(String, Vec<DID>, bool),
RemoveConversation(Uuid),
SetConversation(Uuid),
SetConversationName(String),
Expand All @@ -1021,7 +1021,7 @@ fn list_commands_and_help() -> String {
Command::CreateConversation(DID::default()),
Command::AddRecipient(DID::default()),
Command::RemoveRecipient(DID::default()),
Command::CreateGroupConversation("".into(), vec![]),
Command::CreateGroupConversation("".into(), vec![], false),
Command::RemoveConversation(Uuid::nil()),
Command::SetConversation(Uuid::nil()),
Command::SetConversationName("".into()),
Expand All @@ -1048,7 +1048,7 @@ fn list_commands_and_help() -> String {
Command::CreateConversation(_) => "/create <did> - create conversation with another user",
Command::AddRecipient(_) => "/add-recipient <did> - add recipient to conversation",
Command::RemoveRecipient(_) => "/remove-recipient <did> - remove recipient from conversation",
Command::CreateGroupConversation(_, _) => "/create-group <name> <did> ... - create group conversation with other users",
Command::CreateGroupConversation(_, _, _) => "/create-group [--open] <name> <did> ... - create group conversation with other users",
Command::RemoveConversation(_) => "/remove-conversation - delete current conversation. This will delete it on both ends",
Command::SetConversation(_) => "/set-conversation <id> - switch to a conversation",
Command::SetConversationName(_) => "/set-conversation-name <name> - set conversation name",
Expand Down Expand Up @@ -1130,11 +1130,11 @@ impl FromStr for Command {
Some("/create-group") => {
let mut did_keys = vec![];

let name = match cmd_line.next() {
Some(name) => name,
None => {
return Err(anyhow::anyhow!("/create-group <name> <DID> ..."));
}
let usage_error_fn = || anyhow::anyhow!("/create-group [--open] <name> <DID> ...");
let (name, open) = match cmd_line.next() {
Some("--open") => (cmd_line.next().ok_or_else(usage_error_fn)?, true),
Some(name) => (name, false),
None => return Err(usage_error_fn()),
};

for item in cmd_line.by_ref() {
Expand All @@ -1144,7 +1144,11 @@ impl FromStr for Command {
did_keys.push(did);
}

Ok(Command::CreateGroupConversation(name.to_string(), did_keys))
Ok(Command::CreateGroupConversation(
name.to_string(),
did_keys,
open,
))
}
Some("/remove-conversation") => {
let conversation_id = match cmd_line.next() {
Expand Down
3 changes: 2 additions & 1 deletion extensions/warp-ipfs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1363,9 +1363,10 @@ impl RayGun for WarpIpfs {
&mut self,
name: Option<String>,
recipients: Vec<DID>,
open: bool,
) -> Result<Conversation, Error> {
self.messaging_store()?
.create_group_conversation(name, HashSet::from_iter(recipients))
.create_group_conversation(name, HashSet::from_iter(recipients), open)
.await
}

Expand Down
35 changes: 22 additions & 13 deletions extensions/warp-ipfs/src/store/conversation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,14 +207,19 @@ impl ConversationDocument {
)
}

pub fn new_group(did: &DID, name: Option<String>, recipients: &[DID]) -> Result<Self, Error> {
pub fn new_group(
did: &DID,
name: Option<String>,
recipients: &[DID],
open: bool,
) -> Result<Self, Error> {
let conversation_id = Some(Uuid::new_v4());
Self::new(
did,
name,
recipients.to_vec(),
conversation_id,
ConversationType::Group,
ConversationType::Group { open },
None,
None,
Some(did.clone()),
Expand All @@ -225,32 +230,34 @@ impl ConversationDocument {

impl ConversationDocument {
pub fn sign(&mut self, did: &DID) -> Result<(), Error> {
if matches!(self.conversation_type, ConversationType::Group) {
if let ConversationType::Group { open } = self.conversation_type {
let Some(creator) = self.creator.clone() else {
return Err(Error::PublicKeyInvalid);
};

if !creator.eq(did) {
if !open && !creator.eq(did) {
return Err(Error::PublicKeyInvalid);
}

let construct = vec![
let mut construct = vec![
self.id().into_bytes().to_vec(),
vec![0xdc, 0xfc],
creator.to_string().as_bytes().to_vec(),
Vec::from_iter(
];
if !open {
construct.push(Vec::from_iter(
self.recipients
.iter()
.flat_map(|rec| rec.to_string().as_bytes().to_vec()),
),
];
));
}
self.signature = Some(bs58::encode(did.sign(&construct.concat())).into_string());
}
Ok(())
}

pub fn verify(&self) -> Result<(), Error> {
if matches!(self.conversation_type, ConversationType::Group) {
if let ConversationType::Group { open } = self.conversation_type {
let Some(creator) = &self.creator else {
return Err(Error::PublicKeyInvalid);
};
Expand All @@ -261,16 +268,18 @@ impl ConversationDocument {

let signature = bs58::decode(signature).into_vec()?;

let construct = vec![
let mut construct = vec![
self.id().into_bytes().to_vec(),
vec![0xdc, 0xfc],
creator.to_string().as_bytes().to_vec(),
Vec::from_iter(
];
if !open {
construct.push(Vec::from_iter(
self.recipients
.iter()
.flat_map(|rec| rec.to_string().as_bytes().to_vec()),
),
];
));
}

creator
.verify(&construct.concat(), &signature)
Expand Down
2 changes: 1 addition & 1 deletion extensions/warp-ipfs/src/store/document/conversation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ impl ConversationTask {
async fn set_document(&mut self, mut document: ConversationDocument) -> Result<(), Error> {
if let Some(creator) = document.creator.as_ref() {
if creator.eq(&self.keypair)
&& matches!(document.conversation_type, ConversationType::Group)
&& matches!(document.conversation_type, ConversationType::Group { .. })
{
document.sign(&self.keypair)?;
}
Expand Down
Loading

0 comments on commit db62e0c

Please sign in to comment.