use std::sync::{Arc, PoisonError, RwLock};
#[derive(Debug, Clone, Default)]
pub struct Account(Arc<RwLock<Who>>);
#[derive(Debug, Default)]
struct Who {
host: String,
fingerprint: String,
login: Option<String>,
}
impl Account {
pub fn new(host: &str, fingerprint: &str, login: Option<String>) -> Self {
Self(Arc::new(RwLock::new(Who {
host: host.to_owned(),
fingerprint: fingerprint.to_owned(),
login,
})))
}
pub fn scope(&self) -> String {
let who = self.0.read().unwrap_or_else(PoisonError::into_inner);
match &who.login {
_ if who.host.is_empty() => String::new(),
Some(login) => format!("{}/{login}/", who.host),
None => format!("{}/token-{}/", who.host, who.fingerprint),
}
}
pub fn login(&self) -> Option<String> {
let who = self.0.read().unwrap_or_else(PoisonError::into_inner);
who.login.clone()
}
pub(crate) fn token_key(&self) -> Option<String> {
let who = self.0.read().unwrap_or_else(PoisonError::into_inner);
(!who.host.is_empty()).then(|| format!("{}/{}", who.host, who.fingerprint))
}
pub(crate) fn sign_in(&self, login: &str) -> bool {
let mut who = self.0.write().unwrap_or_else(PoisonError::into_inner);
if who.host.is_empty() || who.login.as_deref() == Some(login) {
return false;
}
who.login = Some(login.to_owned());
true
}
}