2021-02-04 22:24:01 +01:00
|
|
|
use crate::{Backend, Result};
|
2021-02-04 21:47:22 +01:00
|
|
|
use musicus_client::LoginData;
|
2020-11-14 22:32:21 +01:00
|
|
|
use futures_channel::oneshot;
|
|
|
|
|
use secret_service::{Collection, EncryptionType, SecretService};
|
2021-02-04 16:14:42 +01:00
|
|
|
use std::collections::HashMap;
|
|
|
|
|
use std::thread;
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
impl Backend {
|
|
|
|
|
/// Get the login credentials from secret storage.
|
|
|
|
|
pub(super) async fn load_login_data() -> Result<Option<LoginData>> {
|
|
|
|
|
let (sender, receiver) = oneshot::channel();
|
|
|
|
|
thread::spawn(move || sender.send(Self::load_login_data_priv()).unwrap());
|
|
|
|
|
receiver.await?
|
|
|
|
|
}
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
/// 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?
|
|
|
|
|
}
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
/// Get the login credentials from secret storage.
|
|
|
|
|
fn load_login_data_priv() -> Result<Option<LoginData>> {
|
|
|
|
|
let ss = SecretService::new(EncryptionType::Dh)?;
|
|
|
|
|
let collection = Self::get_collection(&ss)?;
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
let items = collection.get_all_items()?;
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
let key = "musicus-login-data";
|
|
|
|
|
let item = items.iter().find(|item| item.get_label().unwrap_or_default() == key);
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
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();
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
Some(LoginData { username, password })
|
|
|
|
|
}
|
|
|
|
|
None => None,
|
|
|
|
|
})
|
|
|
|
|
}
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
/// 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)?;
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
let key = "musicus-login-data";
|
|
|
|
|
Self::delete_secrets(&collection, key)?;
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
let mut attributes = HashMap::new();
|
|
|
|
|
attributes.insert("username", data.username.as_str());
|
|
|
|
|
collection.create_item(key, attributes, data.password.as_bytes(), true, "text/plain")?;
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Delete all stored secrets for the provided key.
|
|
|
|
|
fn delete_secrets(collection: &Collection, key: &str) -> Result<()> {
|
|
|
|
|
let items = collection.get_all_items()?;
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
for item in items {
|
|
|
|
|
if item.get_label().unwrap_or_default() == key {
|
|
|
|
|
item.delete()?;
|
|
|
|
|
}
|
2020-11-14 22:32:21 +01:00
|
|
|
}
|
|
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
Ok(())
|
|
|
|
|
}
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
/// Get the default SecretService collection and unlock it.
|
|
|
|
|
fn get_collection<'a>(ss: &'a SecretService) -> Result<Collection<'a>> {
|
|
|
|
|
let collection = ss.get_default_collection()?;
|
|
|
|
|
collection.unlock()?;
|
2020-11-14 22:32:21 +01:00
|
|
|
|
2021-02-04 22:24:01 +01:00
|
|
|
Ok(collection)
|
|
|
|
|
}
|
2020-11-14 22:32:21 +01:00
|
|
|
}
|