1use std::sync::Arc;
2
3use crate::client::{Client, ScopeState};
4use crate::error::Error;
5use crate::generated::types::{Account, Identity};
6
7impl Client {
8 pub async fn for_account(&self, account_id: i64) -> Result<Client, Error> {
18 if account_id <= 0 {
19 return Err(Error::usage("account id must be positive"));
20 }
21 let root = Client {
22 shared: self.shared.clone(),
23 account_id: None,
24 scope: Arc::default(),
25 };
26 let identity = root.identity().get().await?;
27 let accessible = identity
28 .accounts
29 .iter()
30 .flatten()
31 .any(|account| account.id == account_id && account_is_accessible(account));
32 if !accessible {
33 return Err(Error::not_found("accessible account", account_id));
34 }
35 let scope = ScopeState::default();
36 *scope.default_sender_id.lock().await = default_sender_for(&identity, Some(account_id));
37 *scope.account_user_id.lock().await = identity
38 .all_users
39 .iter()
40 .flatten()
41 .find(|user| user.account_id == Some(account_id))
42 .map(|user| user.id);
43 Ok(Client {
44 shared: self.shared.clone(),
45 account_id: Some(account_id),
46 scope: Arc::new(scope),
47 })
48 }
49
50 pub async fn default_sender_id(&self) -> Result<i64, Error> {
53 let mut cached = self.scope.default_sender_id.lock().await;
57 if let Some(id) = *cached {
58 return Ok(id);
59 }
60 let identity = self.identity().get().await?;
61 let id = match (
62 default_sender_for(&identity, self.account_id),
63 self.account_id,
64 ) {
65 (Some(id), _) => id,
66 (None, Some(account_id)) => {
67 return Err(Error::not_found("sender for account", account_id));
68 }
69 (None, None) => match identity.primary_contact.as_ref().map(|contact| contact.id) {
70 Some(id) => id,
71 None => return Err(Error::api(0, "no sender found in identity")),
72 },
73 };
74 *cached = Some(id);
75 Ok(id)
76 }
77
78 pub async fn account_user_id(&self) -> Result<i64, Error> {
80 let account_id = self
81 .account_id
82 .ok_or_else(|| Error::usage("account user id needs an account-scoped client"))?;
83 let mut cached = self.scope.account_user_id.lock().await;
86 if let Some(id) = *cached {
87 return Ok(id);
88 }
89 let identity = self.identity().get().await?;
90 match identity
91 .all_users
92 .iter()
93 .flatten()
94 .find(|user| user.account_id == Some(account_id))
95 {
96 Some(user) => {
97 *cached = Some(user.id);
98 Ok(user.id)
99 }
100 None => Err(Error::not_found("user for account", account_id)),
101 }
102 }
103}
104
105fn account_is_accessible(account: &Account) -> bool {
106 let status = account.status.as_deref().unwrap_or_default();
107 let purpose = account.purpose.as_deref().unwrap_or_default();
108 status == "active" || (status == "inactive" && (purpose == "work" || purpose == "domains"))
109}
110
111fn default_sender_for(identity: &Identity, account_id: Option<i64>) -> Option<i64> {
112 let senders: Vec<_> = identity
113 .senders
114 .iter()
115 .flatten()
116 .filter(|sender| account_id.is_none_or(|id| sender.account_id == Some(id)))
117 .collect();
118 senders
119 .iter()
120 .find(|sender| sender.default == Some(true))
121 .or_else(|| senders.first())
122 .map(|sender| sender.id)
123}