use crate::daemon::SettingsKey; use keyring::{Entry, Result}; use std::sync::Arc; use tokio::sync::Mutex; use kordophone::api::{http_client::Credentials, AuthenticationStore}; 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(); 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: String) { self.database .lock() .await .with_settings(|settings| settings.put(SettingsKey::TOKEN, &token)) .await .unwrap_or_else(|e| { log::error!("Failed to set token: {}", e); }); } }