From 8fdb2b20593764075ddddf140952434e7d0dee39 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Sun, 1 May 2022 19:49:09 -0700 Subject: [PATCH 1/3] add allow list contact handling support --- src/imp.rs | 79 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 23 deletions(-) diff --git a/src/imp.rs b/src/imp.rs index 4fbb5e6..a64dded 100644 --- a/src/imp.rs +++ b/src/imp.rs @@ -4,6 +4,21 @@ use libcwtch::CwtchLib; use serde_json; +// Todo: move Behaviour + building to seperate file + +pub struct AllowList { + // list of peers to allow by handle + peers: Vec, + // list of groups to join and listen for peers in peer list from + groups: Vec, +} + +impl AllowList { + pub fn new(peers: Vec, groups: Vec) -> Self { + AllowList{peers: peers, groups: groups} + } +} + /// How new contacts should be treated pub enum NewContactPolicy { /// Do not react, leave it for the custom event handler @@ -12,6 +27,9 @@ pub enum NewContactPolicy { Block, /// Accept all new contacts Accept, + /// AllowList is a list of handles that connections will be allowed from and connected to, and will be accepted + /// everything else will be ignored + AllowList(AllowList) } /// Settings for the bot on how it should automatically behave @@ -89,12 +107,12 @@ impl BehaviourBuilder { /// Trait to be used by implementors of imp bots to supply their custom event handling /// the handle function is called after the default imp automatic event handling has run on each new event pub trait EventHandler { - fn handle(&mut self, cwtch: &dyn CwtchLib, profile: Option<&Profile>, event: Event); + fn handle(&mut self, cwtch: &dyn libcwtch::CwtchLib, profile: Option<&Profile>, event: Event); } /// Cwtch bot pub struct Imp { - cwtch: Box, + cwtch: Box, behaviour: Behaviour, password: String, home_dir: String, @@ -213,16 +231,7 @@ impl Imp { ); for (_id, conversation) in &profile.conversations { - match self.behaviour.new_contant_policy { - NewContactPolicy::Accept => { - self.cwtch - .accept_conversation(&profile.handle.clone(), conversation.identifier); - } - NewContactPolicy::Block => self - .cwtch - .block_contact(&profile.handle.clone(), conversation.identifier), - NewContactPolicy::Ignore => (), - } + self.process_contact(conversation.identifier); } self.profile = Some(profile); @@ -236,7 +245,6 @@ impl Imp { Event::ContactCreated { data } => { println!("Contact Created"); let convo_handle = data["RemotePeer"].to_string(); - let convo_id = data["ConversationID"].parse::().unwrap(); let acl: ACL = serde_json::from_str(&data["accessControlList"]).expect("Error parsing conversation"); @@ -251,20 +259,13 @@ impl Imp { is_group: false, // by definition }; + self.process_contact(conversation.identifier); + match self.profile.as_mut() { Some(profile) => { profile .conversations - .insert(data["RemotePeer"].to_string(), conversation); - - match self.behaviour.new_contant_policy { - NewContactPolicy::Accept => { - self.cwtch - .accept_conversation(&profile.handle.clone(), convo_id); - } - NewContactPolicy::Block => self.cwtch.block_contact(&profile.handle.clone(), convo_id), - NewContactPolicy::Ignore => (), - } + .insert(conversation.identifier, conversation); } None => (), }; @@ -277,4 +278,36 @@ impl Imp { handler.handle(self.cwtch.as_ref(), self.profile.as_ref(), event); } } + + fn process_contact(&self, conversation_id: i32) { + match &self.profile { + Some(profile) => { + let profile_handle = profile.handle.clone(); + + + match &self.behaviour.new_contant_policy { + NewContactPolicy::Accept => { + self.cwtch + .accept_conversation(&profile_handle.clone(), conversation_id); + } + NewContactPolicy::Block => self.cwtch.block_contact(&profile_handle.clone(), conversation_id), + NewContactPolicy::AllowList(allow_list) => { + match profile.conversations.get(&conversation_id) { + Some(conversation) => { + if allow_list.peers.contains(&conversation.handle) { + self.cwtch + .accept_conversation(&profile_handle.clone(), conversation_id); + } else { + self.cwtch.block_contact(&profile_handle.clone(), conversation_id); + } + }, + None => {}, + } + } + NewContactPolicy::Ignore => (), + } + }, + None => {}, + } + } } From eafe7a0ae546276447dd2e39c0f732d696a11690 Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Mon, 2 May 2022 10:23:05 -0700 Subject: [PATCH 2/3] add contacts from allow list --- src/imp.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/imp.rs b/src/imp.rs index a64dded..df56cd7 100644 --- a/src/imp.rs +++ b/src/imp.rs @@ -3,19 +3,20 @@ use libcwtch::structs::*; use libcwtch::CwtchLib; use serde_json; +use crate::imp::NewContactPolicy::AllowList; // Todo: move Behaviour + building to seperate file -pub struct AllowList { +pub struct AllowListMembers { // list of peers to allow by handle peers: Vec, // list of groups to join and listen for peers in peer list from groups: Vec, } -impl AllowList { +impl AllowListMembers { pub fn new(peers: Vec, groups: Vec) -> Self { - AllowList{peers: peers, groups: groups} + AllowListMembers {peers: peers, groups: groups} } } @@ -29,7 +30,7 @@ pub enum NewContactPolicy { Accept, /// AllowList is a list of handles that connections will be allowed from and connected to, and will be accepted /// everything else will be ignored - AllowList(AllowList) + AllowList(AllowListMembers) } /// Settings for the bot on how it should automatically behave @@ -234,10 +235,19 @@ impl Imp { self.process_contact(conversation.identifier); } + // Allow list should add all people in the list + if let AllowList(allow_list) = &self.behaviour.new_contant_policy { + for handle in &allow_list.peers { + if let None = profile.find_conversation_id_by_handle(handle.clone()) { + self.cwtch.import_bundle(&profile.handle.clone(), &handle.clone()); + } + } + } + self.profile = Some(profile); } Event::AppError { data } => { - if initialized && data["Error"] == "Loaded 0 profiles" { + if initialized && data.contains_key("Error") && data["Error"] == "Loaded 0 profiles" { self.cwtch .create_profile(&self.behaviour.profile_name, &self.password); } From 8144b87adca67b87da91d577c18d3ff9250843fc Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Mon, 2 May 2022 14:43:43 -0700 Subject: [PATCH 3/3] break out behaviour --- Cargo.toml | 2 +- src/behaviour.rs | 109 +++++++++++++++++++++++++++++++++++++++++++++++ src/imp.rs | 103 +------------------------------------------- src/lib.rs | 1 + 4 files changed, 113 insertions(+), 102 deletions(-) create mode 100644 src/behaviour.rs diff --git a/Cargo.toml b/Cargo.toml index 93b9aff..6d26f1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -libcwtch = "0.3.0" +libcwtch = "0.3.2" serde_json = "1.0" chrono = "0.4.19" \ No newline at end of file diff --git a/src/behaviour.rs b/src/behaviour.rs new file mode 100644 index 0000000..fdadd17 --- /dev/null +++ b/src/behaviour.rs @@ -0,0 +1,109 @@ + +/// defines a locked list of allowed peers and groups the bot may communicate with +/// others will be blocked, and peers listed here will be peered with actively +pub struct AllowListMembers { + /// list of peers to allow by handle + pub peers: Vec, + /// list of groups to join and listen for peers in peer list from + pub groups: Vec, +} + +impl AllowListMembers { + /// constructs a new AllowListMembers struct + pub fn new(peers: Vec, groups: Vec) -> Self { + AllowListMembers {peers: peers, groups: groups} + } +} + +/// How new contacts should be treated +pub enum NewContactPolicy { + /// Do not react, leave it for the custom event handler + Ignore, + /// Block all new contacts + Block, + /// Accept all new contacts + Accept, + /// AllowList is a list of handles that connections will be allowed from and connected to, and will be accepted + /// everything else will be ignored + AllowList(AllowListMembers) +} + +/// Settings for the bot on how it should automatically behave +pub struct Behaviour { + /// The bot will enable experimental feautres (required for any experiments to be used) + pub proto_experiments: bool, + + /// The bot will enable the file sharing experiment + pub proto_experiment_fileshare: bool, + + /// The bot will enable the groups experiment + pub proto_experiment_groups: bool, + + /// The profile name the bot will share with accepted conversations + pub profile_name: String, + /// The profile pic the bot with share with accepted conversations IF the file share exoeriment is enabled + pub profile_pic_path: Option, + + /// Policy dictacting how the bot should automatically handle ContactCreated events + pub new_contant_policy: NewContactPolicy, +} + +/// intermediary struct for building a Behaviour using builder patern +pub struct BehaviourBuilder { + behaviour: Behaviour, +} + +impl BehaviourBuilder { + /// Returns a new empty default off for features behaviour builder + pub fn new() -> Self { + return BehaviourBuilder { + behaviour: Behaviour { + proto_experiments: false, + proto_experiment_fileshare: false, + proto_experiment_groups: false, + new_contant_policy: NewContactPolicy::Ignore, + profile_name: "".to_string(), + profile_pic_path: None, + }, + }; + } + + /// Build the defined behaviours into a Behaviour struct + pub fn build(self) -> Behaviour { + self.behaviour + } + + /// Control if the Behaviour of the bot should include groups (enabling experiments and the group experiment) + pub fn groups(mut self, val: bool) -> Self { + self.behaviour.proto_experiment_groups = val; + self.behaviour.proto_experiments = true; + self + } + + /// Control if the Behaviour of the bot should include filesharing (enabling experiments and the filesharing experiment) + pub fn fileshare(mut self, val: bool) -> Self { + self.behaviour.proto_experiment_fileshare = val; + self.behaviour.proto_experiments = true; + self + } + + /// Set a profile pic for the bot and enable the filesharing experiment + pub fn profile_pic_path(mut self, val: String) -> Self { + self.behaviour.profile_pic_path = Some(val); + self.behaviour.proto_experiment_fileshare = true; + self.behaviour.proto_experiments = true; + self + } + + /// Set a name for the behaviour + pub fn name(mut self, val: String) -> Self { + self.behaviour.profile_name = val; + self + } + + /// Set a new contact policy for the behaviour + pub fn new_contact_policy(mut self, val: NewContactPolicy) -> Self { + self.behaviour.new_contant_policy = val; + self + } +} diff --git a/src/imp.rs b/src/imp.rs index df56cd7..8860191 100644 --- a/src/imp.rs +++ b/src/imp.rs @@ -3,107 +3,8 @@ use libcwtch::structs::*; use libcwtch::CwtchLib; use serde_json; -use crate::imp::NewContactPolicy::AllowList; - -// Todo: move Behaviour + building to seperate file - -pub struct AllowListMembers { - // list of peers to allow by handle - peers: Vec, - // list of groups to join and listen for peers in peer list from - groups: Vec, -} - -impl AllowListMembers { - pub fn new(peers: Vec, groups: Vec) -> Self { - AllowListMembers {peers: peers, groups: groups} - } -} - -/// How new contacts should be treated -pub enum NewContactPolicy { - /// Do not react, leave it for the custom event handler - Ignore, - /// Block all new contacts - Block, - /// Accept all new contacts - Accept, - /// AllowList is a list of handles that connections will be allowed from and connected to, and will be accepted - /// everything else will be ignored - AllowList(AllowListMembers) -} - -/// Settings for the bot on how it should automatically behave -pub struct Behaviour { - /// The bot will enable experimental feautres (required for any experiments to be used) - pub proto_experiments: bool, - - /// The bot will enable the file sharing experiment - pub proto_experiment_fileshare: bool, - - /// The bot will enable the groups experiment - pub proto_experiment_groups: bool, - - /// The profile name the bot will share with accepted conversations - pub profile_name: String, - /// The profile pic the bot with share with accepted conversations IF the file share exoeriment is enabled - pub profile_pic_path: Option, - - /// Policy dictacting how the bot should automatically handle ContactCreated events - pub new_contant_policy: NewContactPolicy, -} - -pub struct BehaviourBuilder { - behaviour: Behaviour, -} - -impl BehaviourBuilder { - pub fn new() -> Self { - return BehaviourBuilder { - behaviour: Behaviour { - proto_experiments: false, - proto_experiment_fileshare: false, - proto_experiment_groups: false, - new_contant_policy: NewContactPolicy::Ignore, - profile_name: "".to_string(), - profile_pic_path: None, - }, - }; - } - - pub fn build(self) -> Behaviour { - self.behaviour - } - - pub fn groups(mut self, val: bool) -> Self { - self.behaviour.proto_experiment_groups = val; - self.behaviour.proto_experiments = true; - self - } - - pub fn fileshare(mut self, val: bool) -> Self { - self.behaviour.proto_experiment_fileshare = val; - self.behaviour.proto_experiments = true; - self - } - - pub fn profile_pic_path(mut self, val: String) -> Self { - self.behaviour.profile_pic_path = Some(val); - self.behaviour.proto_experiment_fileshare = true; - self.behaviour.proto_experiments = true; - self - } - - pub fn name(mut self, val: String) -> Self { - self.behaviour.profile_name = val; - self - } - - pub fn new_contact_policy(mut self, val: NewContactPolicy) -> Self { - self.behaviour.new_contant_policy = val; - self - } -} +use crate::behaviour::{Behaviour, NewContactPolicy}; +use crate::behaviour::NewContactPolicy::AllowList; /// Trait to be used by implementors of imp bots to supply their custom event handling /// the handle function is called after the default imp automatic event handling has run on each new event diff --git a/src/lib.rs b/src/lib.rs index 171f4a1..0c2d3b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,3 @@ pub mod event; pub mod imp; +pub mod behaviour;