mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 19:57:25 +01:00
Port to secret_service 2.0
This commit is contained in:
parent
df78aa17ad
commit
4ad7a1fb28
2 changed files with 22 additions and 59 deletions
|
|
@ -19,7 +19,7 @@ gstreamer-player = "0.16.3"
|
||||||
isahc = "0.9.12"
|
isahc = "0.9.12"
|
||||||
once_cell = "1.5.2"
|
once_cell = "1.5.2"
|
||||||
rand = "0.7.3"
|
rand = "0.7.3"
|
||||||
secret-service = "1.1.1"
|
secret-service = "2.0.1"
|
||||||
serde = { version = "1.0.117", features = ["derive"] }
|
serde = { version = "1.0.117", features = ["derive"] }
|
||||||
serde_json = "1.0.59"
|
serde_json = "1.0.59"
|
||||||
uuid = { version = "0.8", features = ["v4"] }
|
uuid = { version = "0.8", features = ["v4"] }
|
||||||
|
|
|
||||||
|
|
@ -1,71 +1,47 @@
|
||||||
use super::LoginData;
|
use crate::backend::LoginData;
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::Result;
|
||||||
use futures_channel::oneshot;
|
use futures_channel::oneshot;
|
||||||
use secret_service::{Collection, EncryptionType, SecretService};
|
use secret_service::{Collection, EncryptionType, SecretService};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
/// Savely store the user's current login credentials.
|
/// Savely store the user's current login credentials.
|
||||||
pub async fn store_login_data(data: LoginData) -> Result<()> {
|
pub async fn store_login_data(data: LoginData) -> Result<()> {
|
||||||
let (sender, receiver) = oneshot::channel::<Result<()>>();
|
let (sender, receiver) = oneshot::channel();
|
||||||
std::thread::spawn(move || sender.send(store_login_data_priv(data)));
|
thread::spawn(move || sender.send(store_login_data_priv(data)).unwrap());
|
||||||
receiver.await?
|
receiver.await?
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Savely store the user's current login credentials.
|
/// Savely store the user's current login credentials.
|
||||||
fn store_login_data_priv(data: LoginData) -> Result<()> {
|
fn store_login_data_priv(data: LoginData) -> Result<()> {
|
||||||
let ss = get_ss()?;
|
let ss = SecretService::new(EncryptionType::Dh)?;
|
||||||
let collection = get_collection(&ss)?;
|
let collection = get_collection(&ss)?;
|
||||||
|
|
||||||
let key = "musicus-login-data";
|
let key = "musicus-login-data";
|
||||||
delete_secrets(&collection, key)?;
|
delete_secrets(&collection, key)?;
|
||||||
|
|
||||||
collection
|
let mut attributes = HashMap::new();
|
||||||
.create_item(
|
attributes.insert("username", data.username.as_str());
|
||||||
key,
|
collection.create_item(key, attributes, data.password.as_bytes(), true, "text/plain")?;
|
||||||
vec![("username", &data.username)],
|
|
||||||
data.password.as_bytes(),
|
|
||||||
true,
|
|
||||||
"text/plain",
|
|
||||||
)
|
|
||||||
.or(Err(anyhow!(
|
|
||||||
"Failed to save login data using SecretService!"
|
|
||||||
)))?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the login credentials from secret storage.
|
/// Get the login credentials from secret storage.
|
||||||
pub fn load_login_data() -> Result<Option<LoginData>> {
|
pub fn load_login_data() -> Result<Option<LoginData>> {
|
||||||
let ss = get_ss()?;
|
let ss = SecretService::new(EncryptionType::Dh)?;
|
||||||
let collection = get_collection(&ss)?;
|
let collection = get_collection(&ss)?;
|
||||||
|
|
||||||
let items = collection.get_all_items().or(Err(anyhow!(
|
let items = collection.get_all_items()?;
|
||||||
"Failed to get items from SecretService collection!"
|
|
||||||
)))?;
|
|
||||||
|
|
||||||
let key = "musicus-login-data";
|
let key = "musicus-login-data";
|
||||||
let item = items
|
let item = items.iter().find(|item| item.get_label().unwrap_or_default() == key);
|
||||||
.iter()
|
|
||||||
.find(|item| item.get_label().unwrap_or_default() == key);
|
|
||||||
|
|
||||||
Ok(match item {
|
Ok(match item {
|
||||||
Some(item) => {
|
Some(item) => {
|
||||||
let attrs = item.get_attributes().or(Err(anyhow!(
|
// TODO: Delete the item when malformed.
|
||||||
"Failed to get attributes for ScretService item!"
|
let username = item.get_attributes()?.get("username").unwrap().to_owned();
|
||||||
)))?;
|
let password = std::str::from_utf8(&item.get_secret()?)?.to_owned();
|
||||||
|
|
||||||
let username = attrs
|
|
||||||
.iter()
|
|
||||||
.find(|attr| attr.0 == "username")
|
|
||||||
.ok_or(anyhow!("No username in login data!"))?
|
|
||||||
.1
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
let password = std::str::from_utf8(
|
|
||||||
&item
|
|
||||||
.get_secret()
|
|
||||||
.or(Err(anyhow!("Failed to get secret from SecretService!")))?,
|
|
||||||
)?
|
|
||||||
.to_string();
|
|
||||||
|
|
||||||
Some(LoginData { username, password })
|
Some(LoginData { username, password })
|
||||||
}
|
}
|
||||||
|
|
@ -75,34 +51,21 @@ pub fn load_login_data() -> Result<Option<LoginData>> {
|
||||||
|
|
||||||
/// Delete all stored secrets for the provided key.
|
/// Delete all stored secrets for the provided key.
|
||||||
fn delete_secrets(collection: &Collection, key: &str) -> Result<()> {
|
fn delete_secrets(collection: &Collection, key: &str) -> Result<()> {
|
||||||
let items = collection.get_all_items().or(Err(anyhow!(
|
let items = collection.get_all_items()?;
|
||||||
"Failed to get items from SecretService collection!"
|
|
||||||
)))?;
|
|
||||||
|
|
||||||
for item in items {
|
for item in items {
|
||||||
if item.get_label().unwrap_or_default() == key {
|
if item.get_label().unwrap_or_default() == key {
|
||||||
item.delete()
|
item.delete()?;
|
||||||
.or(Err(anyhow!("Failed to delete SecretService item!")))?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the SecretService interface.
|
|
||||||
fn get_ss() -> Result<SecretService> {
|
|
||||||
SecretService::new(EncryptionType::Dh).or(Err(anyhow!("Failed to get SecretService!")))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the default SecretService collection and unlock it.
|
/// Get the default SecretService collection and unlock it.
|
||||||
fn get_collection(ss: &SecretService) -> Result<Collection> {
|
fn get_collection<'a>(ss: &'a SecretService) -> Result<Collection<'a>> {
|
||||||
let collection = ss
|
let collection = ss.get_default_collection()?;
|
||||||
.get_default_collection()
|
collection.unlock()?;
|
||||||
.or(Err(anyhow!("Failed to get SecretService connection!")))?;
|
|
||||||
|
|
||||||
collection
|
|
||||||
.unlock()
|
|
||||||
.or(Err(anyhow!("Failed to unclock SecretService collection!")))?;
|
|
||||||
|
|
||||||
Ok(collection)
|
Ok(collection)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue