use crate::daemon::SettingsKey; use std::sync::Arc; use tokio::sync::Mutex; use keyring::{Entry, Result}; use kordophone::api::{AuthenticationStore, http_client::Credentials}; use kordophone::model::JwtToken; use kordophone_db::database::{Database, DatabaseAccess}; use async_trait::async_trait; pub struct DatabaseAuthenticationStore { database: Arc>, } impl DatabaseAuthenticationStore { pub fn new(database: Arc>) -> Self { Self { database } } } #[async_trait] impl AuthenticationStore for DatabaseAuthenticationStore { async fn get_credentials(&mut self) -> Option { use keyring::secret_service::SsCredential; self.database.lock().await.with_settings(|settings| { let username: Option = settings.get::(SettingsKey::USERNAME) .unwrap_or_else(|e| { log::warn!("error getting username from database: {}", e); None }); match username { Some(username) => { let credential = SsCredential::new_with_target(None, "net.buzzert.kordophonecd", &username).unwrap(); let password: Result = Entry::new_with_credential(Box::new(credential)) .get_password(); log::debug!("password: {:?}", password); match password { Ok(password) => Some(Credentials { username, password }), Err(e) => { log::error!("error getting password from keyring: {}", e); None } } } None => None, } }).await } async fn get_token(&mut self) -> Option { self.database.lock().await .with_settings(|settings| { match settings.get::(SettingsKey::TOKEN) { Ok(token) => token, Err(e) => { log::warn!("Failed to get token from settings: {}", e); None } } }).await } async fn set_token(&mut self, token: JwtToken) { self.database.lock().await .with_settings(|settings| settings.put(SettingsKey::TOKEN, &token)).await.unwrap_or_else(|e| { log::error!("Failed to set token: {}", e); }); } }