use std::sync::Arc;
use crate::client::{Client, ScopeState};
use crate::error::Error;
use crate::generated::types::{Account, Identity};
impl Client {
pub async fn for_account(&self, account_id: i64) -> Result<Client, Error> {
if account_id <= 0 {
return Err(Error::usage("account id must be positive"));
}
let root = Client {
shared: self.shared.clone(),
account_id: None,
scope: Arc::default(),
};
let identity = root.identity().get().await?;
let accessible = identity
.accounts
.iter()
.flatten()
.any(|account| account.id == account_id && account_is_accessible(account));
if !accessible {
return Err(Error::not_found("accessible account", account_id));
}
let scope = ScopeState::default();
*scope.default_sender_id.lock().await = default_sender_for(&identity, Some(account_id));
*scope.account_user_id.lock().await = identity
.all_users
.iter()
.flatten()
.find(|user| user.account_id == Some(account_id))
.map(|user| user.id);
Ok(Client {
shared: self.shared.clone(),
account_id: Some(account_id),
scope: Arc::new(scope),
})
}
pub async fn default_sender_id(&self) -> Result<i64, Error> {
let mut cached = self.scope.default_sender_id.lock().await;
if let Some(id) = *cached {
return Ok(id);
}
let identity = self.identity().get().await?;
let id = match (
default_sender_for(&identity, self.account_id),
self.account_id,
) {
(Some(id), _) => id,
(None, Some(account_id)) => {
return Err(Error::not_found("sender for account", account_id));
}
(None, None) => match identity.primary_contact.as_ref().map(|contact| contact.id) {
Some(id) => id,
None => return Err(Error::api(0, "no sender found in identity")),
},
};
*cached = Some(id);
Ok(id)
}
pub async fn account_user_id(&self) -> Result<i64, Error> {
let account_id = self
.account_id
.ok_or_else(|| Error::usage("account user id needs an account-scoped client"))?;
let mut cached = self.scope.account_user_id.lock().await;
if let Some(id) = *cached {
return Ok(id);
}
let identity = self.identity().get().await?;
match identity
.all_users
.iter()
.flatten()
.find(|user| user.account_id == Some(account_id))
{
Some(user) => {
*cached = Some(user.id);
Ok(user.id)
}
None => Err(Error::not_found("user for account", account_id)),
}
}
}
fn account_is_accessible(account: &Account) -> bool {
let status = account.status.as_deref().unwrap_or_default();
let purpose = account.purpose.as_deref().unwrap_or_default();
status == "active" || (status == "inactive" && (purpose == "work" || purpose == "domains"))
}
fn default_sender_for(identity: &Identity, account_id: Option<i64>) -> Option<i64> {
let senders: Vec<_> = identity
.senders
.iter()
.flatten()
.filter(|sender| account_id.is_none_or(|id| sender.account_id == Some(id)))
.collect();
senders
.iter()
.find(|sender| sender.default == Some(true))
.or_else(|| senders.first())
.map(|sender| sender.id)
}