Remove server synchronization code

This commit (tries to) remove all code for synchronyzing to a music
metadata server. Because the intended use cases of the application have
shifted over time, this isn't a central feature anymore. However, it
may well be decided to reintroduce the functionality at some point in
the future.
This commit is contained in:
Elias Projahn 2022-01-23 13:18:37 +01:00
parent 384ca255f3
commit f165c6cae8
48 changed files with 96 additions and 2633 deletions

View file

@ -10,7 +10,6 @@ glib = "0.14.0"
gstreamer = "0.17.0"
gstreamer-player = "0.17.0"
log = { version = "0.4.14", features = ["std"] }
musicus_client = { version = "0.1.0", path = "../client" }
musicus_database = { version = "0.1.0", path = "../database" }
musicus_import = { version = "0.1.0", path = "../import" }
thiserror = "1.0.23"
@ -18,4 +17,3 @@ tokio = { version = "1.4.0", features = ["sync"] }
[target.'cfg(target_os = "linux")'.dependencies]
mpris-player = "0.6.0"
secret-service = "2.0.1"

View file

@ -1,16 +1,9 @@
/// An error that can happened within the backend.
/// An error that happened within the backend.
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error(transparent)]
ClientError(#[from] musicus_client::Error),
#[error(transparent)]
DatabaseError(#[from] musicus_database::Error),
#[cfg(target_os = "linux")]
#[error("An error happened using the SecretService.")]
SecretServiceError(#[from] secret_service::Error),
#[error("An error happened while decoding to UTF-8.")]
Utf8Error(#[from] std::str::Utf8Error),

View file

@ -1,13 +1,9 @@
use gio::prelude::*;
use log::warn;
use musicus_client::{Client, LoginData};
use musicus_database::DbThread;
use std::cell::{Cell, RefCell};
use std::cell::RefCell;
use std::path::PathBuf;
use std::rc::Rc;
use tokio::sync::{broadcast, broadcast::Sender};
pub use musicus_client as client;
pub use musicus_database as db;
pub use musicus_import as import;
@ -22,9 +18,6 @@ mod logger;
pub mod player;
pub use player::*;
#[cfg(all(feature = "dbus"))]
mod secure;
/// General states the application can be in.
#[derive(Debug, Clone)]
pub enum BackendState {
@ -49,9 +42,6 @@ pub struct Backend {
/// Access to GSettings.
settings: gio::Settings,
/// Whether the server should be used by default when searching for or changing items.
use_server: Cell<bool>,
/// The current path to the music library, which is used by the player and the database. This
/// is guaranteed to be Some, when the state is set to BackendState::Ready.
music_library_path: RefCell<Option<PathBuf>>,
@ -65,9 +55,6 @@ pub struct Backend {
/// The player handling playlist and playback. This can be assumed to exist, when the state is
/// set to BackendState::Ready.
player: RefCell<Option<Rc<Player>>>,
/// A client for the Wolfgang server.
client: Client,
}
impl Backend {
@ -83,12 +70,10 @@ impl Backend {
Backend {
state_sender,
settings: gio::Settings::new("de.johrpan.musicus"),
use_server: Cell::new(true),
music_library_path: RefCell::new(None),
library_updated_sender,
database: RefCell::new(None),
player: RefCell::new(None),
client: Client::new(),
player: RefCell::new(None)
}
}
@ -102,24 +87,6 @@ impl Backend {
pub async fn init(&self) -> Result<()> {
self.init_library().await?;
let url = self.settings.string("server-url");
if !url.is_empty() {
self.client.set_server_url(&url);
}
#[cfg(all(feature = "dbus"))]
match Self::load_login_data().await {
Ok(Some(data)) => self.client.set_login_data(Some(data)),
Err(err) => warn!(
"The login data could not be loaded from SecretService. It will not \
be available. Error message: {}",
err
),
_ => (),
}
self.use_server.set(self.settings.boolean("use-server"));
if self.get_music_library_path().is_none() {
self.set_state(BackendState::NoMusicLibrary);
} else {
@ -129,80 +96,6 @@ impl Backend {
Ok(())
}
/// Whether the server should be used by default.
///
/// This will return `false` if no server URL is set up. Otherwise, the
/// value is based on the users "use-server" preference.
pub fn use_server(&self) -> bool {
self.client.get_server_url().is_some() && self.use_server.get()
}
/// Set whether the server should be used by default.
pub fn set_use_server(&self, enabled: bool) {
self.use_server.set(enabled);
if let Err(err) = self.settings.set_boolean("use-server", enabled) {
warn!(
"An error happened whilte trying to save the \"use-server\" setting to GSettings. \
Error message: {}",
err
)
}
}
/// Set the URL of the Musicus server to connect to.
pub fn set_server_url(&self, url: &str) {
if let Err(err) = self.settings.set_string("server-url", url) {
warn!(
"An error happened while trying to save the server URL to GSettings. Most \
likely it will not be available at the next startup. Error message: {}",
err
);
}
self.client.set_server_url(url);
}
/// Get the currently set server URL.
pub fn get_server_url(&self) -> Option<String> {
self.client.get_server_url()
}
/// Set the user credentials to use.
pub async fn set_login_data(&self, data: Option<LoginData>) {
#[cfg(all(feature = "dbus"))]
if let Some(data) = &data {
if let Err(err) = Self::store_login_data(data.clone()).await {
warn!(
"An error happened while trying to store the login data using SecretService. \
This means, that they will not be available at the next startup most likely. \
Error message: {}",
err
);
}
} else {
if let Err(err) = Self::delete_secrets().await {
warn!(
"An error happened while trying to delete the login data from SecretService. \
This may result in the login data being reloaded at the next startup. Error \
message: {}",
err
);
}
}
self.client.set_login_data(data);
}
pub fn cl(&self) -> &Client {
&self.client
}
/// Get the currently stored login credentials.
pub fn get_login_data(&self) -> Option<LoginData> {
self.client.get_login_data()
}
/// Set the current state and notify the user interface.
fn set_state(&self, state: BackendState) {
self.state_sender.send(state).unwrap();

View file

@ -1,112 +0,0 @@
use crate::{Backend, Error, Result};
use futures_channel::oneshot;
use musicus_client::LoginData;
use secret_service::{Collection, EncryptionType, SecretService};
use std::collections::HashMap;
use std::thread;
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?
}
/// 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?
}
/// Delete all stored secrets.
pub(super) async fn delete_secrets() -> Result<()> {
let (sender, receiver) = oneshot::channel();
thread::spawn(move || sender.send(Self::delete_secrets_priv()).unwrap());
receiver.await?
}
/// 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)?;
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) => {
let username = item
.get_attributes()?
.get("username")
.ok_or(Error::Other(
"Missing username in SecretService attributes.",
))?
.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_for_key(&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.
fn delete_secrets_priv() -> Result<()> {
let ss = SecretService::new(EncryptionType::Dh)?;
let collection = Self::get_collection(&ss)?;
let key = "musicus-login-data";
Self::delete_secrets_for_key(&collection, key)?;
Ok(())
}
/// Delete all stored secrets for the provided key.
fn delete_secrets_for_key(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<Collection<'a>> {
let collection = ss.get_default_collection()?;
collection.unlock()?;
Ok(collection)
}
}