From 9256e6012256151a86d996bd10f832959fdbb8d4 Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Thu, 4 Feb 2021 22:24:01 +0100 Subject: [PATCH] Always use SecretService asynchronously --- crates/musicus_backend/src/lib.rs | 4 +- crates/musicus_backend/src/secure.rs | 129 ++++++++++++++------------- 2 files changed, 71 insertions(+), 62 deletions(-) diff --git a/crates/musicus_backend/src/lib.rs b/crates/musicus_backend/src/lib.rs index 5b6995b..d6f2f89 100644 --- a/crates/musicus_backend/src/lib.rs +++ b/crates/musicus_backend/src/lib.rs @@ -74,7 +74,7 @@ impl Backend { } } - if let Some(data) = secure::load_login_data()? { + if let Some(data) = Self::load_login_data().await? { self.client.set_login_data(data); } @@ -95,7 +95,7 @@ impl Backend { /// Set the user credentials to use. pub async fn set_login_data(&self, data: LoginData) -> Result<()> { - secure::store_login_data(data.clone()).await?; + Self::store_login_data(data.clone()).await?; self.client.set_login_data(data); Ok(()) } diff --git a/crates/musicus_backend/src/secure.rs b/crates/musicus_backend/src/secure.rs index 702015f..02c34e4 100644 --- a/crates/musicus_backend/src/secure.rs +++ b/crates/musicus_backend/src/secure.rs @@ -1,71 +1,80 @@ -use crate::Result; +use crate::{Backend, Result}; use musicus_client::LoginData; use futures_channel::oneshot; use secret_service::{Collection, EncryptionType, SecretService}; use std::collections::HashMap; use std::thread; -/// Savely store the user's current login credentials. -pub async fn store_login_data(data: LoginData) -> Result<()> { - let (sender, receiver) = oneshot::channel(); - thread::spawn(move || sender.send(store_login_data_priv(data)).unwrap()); - receiver.await? -} - -/// Savely store the user's current login credentials. -fn store_login_data_priv(data: LoginData) -> Result<()> { - let ss = SecretService::new(EncryptionType::Dh)?; - let collection = get_collection(&ss)?; - - let key = "musicus-login-data"; - delete_secrets(&collection, key)?; - - let mut attributes = HashMap::new(); - attributes.insert("username", data.username.as_str()); - collection.create_item(key, attributes, data.password.as_bytes(), true, "text/plain")?; - - Ok(()) -} - -/// Get the login credentials from secret storage. -pub fn load_login_data() -> Result> { - let ss = SecretService::new(EncryptionType::Dh)?; - let collection = get_collection(&ss)?; - - let items = collection.get_all_items()?; - - let key = "musicus-login-data"; - let item = items.iter().find(|item| item.get_label().unwrap_or_default() == key); - - Ok(match item { - Some(item) => { - // TODO: Delete the item when malformed. - let username = item.get_attributes()?.get("username").unwrap().to_owned(); - let password = std::str::from_utf8(&item.get_secret()?)?.to_owned(); - - Some(LoginData { username, password }) - } - None => None, - }) -} - -/// Delete all stored secrets for the provided key. -fn delete_secrets(collection: &Collection, key: &str) -> Result<()> { - let items = collection.get_all_items()?; - - for item in items { - if item.get_label().unwrap_or_default() == key { - item.delete()?; - } +impl Backend { + /// Get the login credentials from secret storage. + pub(super) async fn load_login_data() -> Result> { + let (sender, receiver) = oneshot::channel(); + thread::spawn(move || sender.send(Self::load_login_data_priv()).unwrap()); + receiver.await? } - Ok(()) -} + /// Savely store the user's current login credentials. + pub(super) async fn store_login_data(data: LoginData) -> Result<()> { + let (sender, receiver) = oneshot::channel(); + thread::spawn(move || sender.send(Self::store_login_data_priv(data)).unwrap()); + receiver.await? + } -/// Get the default SecretService collection and unlock it. -fn get_collection<'a>(ss: &'a SecretService) -> Result> { - let collection = ss.get_default_collection()?; - collection.unlock()?; + /// Get the login credentials from secret storage. + fn load_login_data_priv() -> Result> { + let ss = SecretService::new(EncryptionType::Dh)?; + let collection = Self::get_collection(&ss)?; - Ok(collection) + let items = collection.get_all_items()?; + + let key = "musicus-login-data"; + let item = items.iter().find(|item| item.get_label().unwrap_or_default() == key); + + Ok(match item { + Some(item) => { + // TODO: Delete the item when malformed. + let username = item.get_attributes()?.get("username").unwrap().to_owned(); + let password = std::str::from_utf8(&item.get_secret()?)?.to_owned(); + + Some(LoginData { username, password }) + } + None => None, + }) + } + + /// Savely store the user's current login credentials. + fn store_login_data_priv(data: LoginData) -> Result<()> { + let ss = SecretService::new(EncryptionType::Dh)?; + let collection = Self::get_collection(&ss)?; + + let key = "musicus-login-data"; + Self::delete_secrets(&collection, key)?; + + let mut attributes = HashMap::new(); + attributes.insert("username", data.username.as_str()); + collection.create_item(key, attributes, data.password.as_bytes(), true, "text/plain")?; + + Ok(()) + } + + /// Delete all stored secrets for the provided key. + fn delete_secrets(collection: &Collection, key: &str) -> Result<()> { + let items = collection.get_all_items()?; + + for item in items { + if item.get_label().unwrap_or_default() == key { + item.delete()?; + } + } + + Ok(()) + } + + /// Get the default SecretService collection and unlock it. + fn get_collection<'a>(ss: &'a SecretService) -> Result> { + let collection = ss.get_default_collection()?; + collection.unlock()?; + + Ok(collection) + } }