diff --git a/src/client.rs b/src/client.rs index 079ea1d..b9c0094 100644 --- a/src/client.rs +++ b/src/client.rs @@ -30,7 +30,7 @@ pub enum Credentials { pub struct Client { session: Session, session_url: String, - session_outdated: AtomicBool, + session_updated: AtomicBool, #[cfg(feature = "websockets")] pub(crate) authorization: String, upload_url: Vec>, @@ -91,7 +91,7 @@ impl Client { event_source_url: URLPart::parse(session.event_source_url())?, session, session_url: url.to_string(), - session_outdated: false.into(), + session_updated: true.into(), #[cfg(feature = "websockets")] authorization, timeout: DEFAULT_TIMEOUT_MS, @@ -147,7 +147,7 @@ impl Client { )?; if response.session_state() != self.session.state() { - self.session_outdated.store(true, Ordering::Relaxed); + self.session_updated.store(false, Ordering::Relaxed); } Ok(response) @@ -172,12 +172,12 @@ impl Client { self.upload_url = URLPart::parse(session.upload_url())?; self.event_source_url = URLPart::parse(session.event_source_url())?; self.session = session; - self.session_outdated.store(false, Ordering::Relaxed); + self.session_updated.store(true, Ordering::Relaxed); Ok(()) } pub fn is_session_updated(&self) -> bool { - !self.session_outdated.load(Ordering::Relaxed) + self.session_updated.load(Ordering::Relaxed) } pub fn set_default_account_id(&mut self, defaul_account_id: impl Into) -> &mut Self { diff --git a/src/email/helpers.rs b/src/email/helpers.rs index 02c35e4..391959d 100644 --- a/src/email/helpers.rs +++ b/src/email/helpers.rs @@ -143,7 +143,7 @@ impl Client { pub async fn email_query( &self, filter: Option>>, - sort: Option>>, + sort: Option>>, ) -> crate::Result { let mut request = self.build(); let query_request = request.query_email(); diff --git a/src/email/mod.rs b/src/email/mod.rs index 7eb6b41..f5cd067 100644 --- a/src/email/mod.rs +++ b/src/email/mod.rs @@ -181,8 +181,8 @@ pub struct Email { #[serde(flatten)] #[serde(skip_deserializing)] - #[serde(skip_serializing_if = "HashMap::is_empty")] - patch: HashMap, + #[serde(skip_serializing_if = "Option::is_none")] + patch: Option>, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/src/email/set.rs b/src/email/set.rs index b874538..3db88e3 100644 --- a/src/email/set.rs +++ b/src/email/set.rs @@ -32,7 +32,9 @@ impl Email { pub fn mailbox_id(&mut self, mailbox_id: &str, set: bool) -> &mut Self { self.mailbox_ids = None; - self.patch.insert(format!("mailboxIds/{}", mailbox_id), set); + self.patch + .get_or_insert_with(HashMap::new) + .insert(format!("mailboxIds/{}", mailbox_id), set); self } @@ -47,7 +49,9 @@ impl Email { pub fn keyword(&mut self, keyword: &str, set: bool) -> &mut Self { self.keywords = None; - self.patch.insert(format!("keywords/{}", keyword), set); + self.patch + .get_or_insert_with(HashMap::new) + .insert(format!("keywords/{}", keyword), set); self } diff --git a/src/mailbox/get.rs b/src/mailbox/get.rs index 28e19e1..d9cad9c 100644 --- a/src/mailbox/get.rs +++ b/src/mailbox/get.rs @@ -1,6 +1,8 @@ -use crate::{core::get::GetObject, Get, Set}; +use std::collections::HashMap; -use super::{Mailbox, Role}; +use crate::{core::get::GetObject, principal::ACL, Get, Set}; + +use super::{Mailbox, MailboxRights, Role}; impl Mailbox { pub fn id(&self) -> &str { @@ -47,40 +49,70 @@ impl Mailbox { *self.is_subscribed.as_ref().unwrap_or(&false) } + pub fn my_rights(&self) -> Option<&MailboxRights> { + self.my_rights.as_ref() + } + + pub fn acl(&self) -> Option<&HashMap>> { + self.acl.as_ref() + } +} + +impl MailboxRights { pub fn may_read_items(&self) -> bool { - self.my_rights.as_ref().unwrap().may_read_items + self.may_read_items } pub fn may_add_items(&self) -> bool { - self.my_rights.as_ref().unwrap().may_add_items + self.may_add_items } pub fn may_remove_items(&self) -> bool { - self.my_rights.as_ref().unwrap().may_remove_items + self.may_remove_items } pub fn may_set_seen(&self) -> bool { - self.my_rights.as_ref().unwrap().may_set_seen + self.may_set_seen } pub fn may_set_keywords(&self) -> bool { - self.my_rights.as_ref().unwrap().may_set_keywords + self.may_set_keywords } pub fn may_create_child(&self) -> bool { - self.my_rights.as_ref().unwrap().may_create_child + self.may_create_child } pub fn may_rename(&self) -> bool { - self.my_rights.as_ref().unwrap().may_rename + self.may_rename } pub fn may_delete(&self) -> bool { - self.my_rights.as_ref().unwrap().may_delete + self.may_delete } pub fn may_submit(&self) -> bool { - self.my_rights.as_ref().unwrap().may_submit + self.may_submit + } + + pub fn acl_list(&self) -> Vec { + let mut acl_list = Vec::new(); + for (is_set, acl) in [ + (self.may_read_items, ACL::ReadItems), + (self.may_add_items, ACL::AddItems), + (self.may_remove_items, ACL::RemoveItems), + (self.may_set_seen, ACL::SetSeen), + (self.may_set_keywords, ACL::SetKeywords), + (self.may_create_child, ACL::CreateChild), + (self.may_rename, ACL::Modify), + (self.may_delete, ACL::Delete), + (self.may_submit, ACL::Submit), + ] { + if is_set { + acl_list.push(acl); + } + } + acl_list } } diff --git a/src/mailbox/helpers.rs b/src/mailbox/helpers.rs index 2b0db85..f81d1fb 100644 --- a/src/mailbox/helpers.rs +++ b/src/mailbox/helpers.rs @@ -9,6 +9,7 @@ use crate::{ response::{MailboxGetResponse, MailboxSetResponse}, set::{SetObject, SetRequest}, }, + principal::ACL, Get, Method, Set, }; @@ -75,6 +76,20 @@ impl Client { .updated(id) } + pub async fn mailbox_update_acl( + &self, + id: &str, + account_id: &str, + acl: impl IntoIterator, + ) -> crate::Result> { + let mut request = self.build(); + request.set_mailbox().update(id).acl(account_id, acl); + request + .send_single::() + .await? + .updated(id) + } + pub async fn mailbox_update_sort_order( &self, id: &str, @@ -104,7 +119,7 @@ impl Client { pub async fn mailbox_get( &self, id: &str, - properties: Option>, + properties: Option>, ) -> crate::Result> { let mut request = self.build(); let get_request = request.get_mailbox().ids([id]); diff --git a/src/mailbox/mod.rs b/src/mailbox/mod.rs index 13ea1c6..80d41fd 100644 --- a/src/mailbox/mod.rs +++ b/src/mailbox/mod.rs @@ -3,12 +3,14 @@ pub mod helpers; pub mod query; pub mod set; +use std::collections::HashMap; use std::fmt::Display; use crate::core::changes::ChangesObject; -use crate::core::set::string_not_set; +use crate::core::set::{map_not_set, string_not_set}; use crate::core::Object; use crate::mailbox::set::role_not_set; +use crate::principal::ACL; use crate::{Get, Set}; use serde::{Deserialize, Serialize}; @@ -84,6 +86,14 @@ pub struct Mailbox { #[serde(rename = "isSubscribed")] #[serde(skip_serializing_if = "Option::is_none")] is_subscribed: Option, + + #[serde(skip_serializing_if = "map_not_set")] + acl: Option>>, + + #[serde(flatten)] + #[serde(skip_deserializing)] + #[serde(skip_serializing_if = "Option::is_none")] + acl_patch: Option>>, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -93,7 +103,7 @@ pub enum Role { Archive, #[serde(rename = "drafts", alias = "DRAFTS")] Drafts, - #[serde(rename = "importante", alias = "IMPORTANT")] + #[serde(rename = "important", alias = "IMPORTANT")] Important, #[serde(rename = "inbox", alias = "INBOX")] Inbox, @@ -160,6 +170,8 @@ pub enum Property { MyRights, #[serde(rename = "isSubscribed")] IsSubscribed, + #[serde(rename = "acl")] + ACL, } impl Display for Property { @@ -176,6 +188,7 @@ impl Display for Property { Property::UnreadThreads => write!(f, "unreadThreads"), Property::MyRights => write!(f, "myRights"), Property::IsSubscribed => write!(f, "isSubscribed"), + Property::ACL => write!(f, "acl"), } } } diff --git a/src/mailbox/set.rs b/src/mailbox/set.rs index a16059f..f8f58d7 100644 --- a/src/mailbox/set.rs +++ b/src/mailbox/set.rs @@ -1,4 +1,6 @@ -use crate::{core::set::SetObject, Get, Set}; +use std::collections::HashMap; + +use crate::{core::set::SetObject, principal::ACL, Get, Set}; use super::{Mailbox, Role, SetArguments}; @@ -31,6 +33,27 @@ impl Mailbox { self.sort_order = sort_order.into(); self } + + pub fn acls(&mut self, acls: T) -> &mut Self + where + T: IntoIterator, + U: Into, + V: IntoIterator, + { + self.acl = Some( + acls.into_iter() + .map(|(id, acls)| (id.into(), acls.into_iter().collect())) + .collect(), + ); + self + } + + pub fn acl(&mut self, id: &str, acl: impl IntoIterator) -> &mut Self { + self.acl_patch + .get_or_insert_with(HashMap::new) + .insert(format!("acl/{}", id), acl.into_iter().collect()); + self + } } pub fn role_not_set(role: &Option) -> bool { @@ -55,6 +78,8 @@ impl SetObject for Mailbox { unread_threads: None, my_rights: None, is_subscribed: None, + acl: HashMap::with_capacity(0).into(), + acl_patch: None, } }