use crate::persist::user::UserProvider; use polariton_server::ToSend; pub struct UserState { state: std::sync::RwLock>, event_tx: tokio::sync::mpsc::UnboundedSender>, } impl UserState { pub async fn update_with_auth(&self, auth_str: &str) -> bool { self.update_with_auth_ext(auth_str, |_| Some(Default::default())).await } pub async fn update_with_auth_ext Option>>>(&self, auth_str: &str, ext_f: F) -> bool { //let mut lock = self.state.write().unwrap(); let init_state_clone = self.state.write().unwrap().clone(); match init_state_clone { InitState::Unauthenticated(auth) => { let splits: Vec<&str> = auth_str.split(';').collect(); if splits.len() != 3 { log::warn!("Invalid auth payload: {}", auth_str); false } else { let token = crate::persist::user::UserToken { uuid: splits[0].to_owned(), token: splits[1].to_owned(), refresh_token: splits[2].to_owned(), }; let ext = if let Some(ext) = ext_f(&token) { ext } else { return false; }; match auth.authenticate(token, ext).await { Ok(user) => { let mut lock = self.state.write().unwrap(); *lock = InitState::Authenticated(std::sync::Arc::new(user)); true }, Err(e) => { log::error!("Failed to authenticate {}: {}", splits[0], e); false } } } }, InitState::Authenticated(_) => { log::warn!("User was already authenticated, ignoring"); true } } } pub fn new(provider: std::sync::Arc, event_tx: tokio::sync::mpsc::UnboundedSender>) -> Self { Self { state: std::sync::RwLock::new(InitState::Unauthenticated(provider)), event_tx, } } pub fn user(&self) -> Result + Send + Sync>>, i16> { let lock = self.state.read().unwrap(); match &*lock { InitState::Unauthenticated(_) => Err(120), InitState::Authenticated(user) => Ok(user.clone()), } } pub fn event(&self, event_data: ToSend) { self.event_tx.send(event_data).unwrap() } pub fn event_sender(&self) -> tokio::sync::mpsc::UnboundedSender> { self.event_tx.clone() } } #[derive(Clone)] enum InitState { Unauthenticated(std::sync::Arc), Authenticated(std::sync::Arc + Send + Sync>>), }