mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 11:47:25 +01:00
Add a way to log out
This commit is contained in:
parent
67fad1329d
commit
5b066a05b6
6 changed files with 126 additions and 35 deletions
|
|
@ -10,15 +10,15 @@ use std::rc::Rc;
|
|||
|
||||
/// A dialog for entering login credentials.
|
||||
pub struct LoginDialog {
|
||||
handle: NavigationHandle<LoginData>,
|
||||
handle: NavigationHandle<Option<LoginData>>,
|
||||
widget: gtk::Stack,
|
||||
info_bar: gtk::InfoBar,
|
||||
username_entry: gtk::Entry,
|
||||
password_entry: gtk::Entry,
|
||||
}
|
||||
|
||||
impl Screen<(), LoginData> for LoginDialog {
|
||||
fn new(_: (), handle: NavigationHandle<LoginData>) -> Rc<Self> {
|
||||
impl Screen<Option<LoginData>, Option<LoginData>> for LoginDialog {
|
||||
fn new(data: Option<LoginData>, handle: NavigationHandle<Option<LoginData>>) -> Rc<Self> {
|
||||
// Create UI
|
||||
let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/login_dialog.ui");
|
||||
|
||||
|
|
@ -28,7 +28,16 @@ impl Screen<(), LoginData> for LoginDialog {
|
|||
get_widget!(builder, gtk::Button, login_button);
|
||||
get_widget!(builder, gtk::Entry, username_entry);
|
||||
get_widget!(builder, gtk::Entry, password_entry);
|
||||
get_widget!(builder, gtk::Box, register_box);
|
||||
get_widget!(builder, gtk::Button, register_button);
|
||||
get_widget!(builder, gtk::Box, logout_box);
|
||||
get_widget!(builder, gtk::Button, logout_button);
|
||||
|
||||
if let Some(data) = data {
|
||||
username_entry.set_text(&data.username);
|
||||
register_box.hide();
|
||||
logout_box.show();
|
||||
}
|
||||
|
||||
let this = Rc::new(Self {
|
||||
handle,
|
||||
|
|
@ -53,9 +62,9 @@ impl Screen<(), LoginData> for LoginDialog {
|
|||
};
|
||||
|
||||
spawn!(@clone this, async move {
|
||||
this.handle.backend.set_login_data(data.clone()).await;
|
||||
this.handle.backend.set_login_data(Some(data.clone())).await;
|
||||
if this.handle.backend.cl().login().await.unwrap() {
|
||||
this.handle.pop(Some(data));
|
||||
this.handle.pop(Some(Some(data)));
|
||||
} else {
|
||||
this.widget.set_visible_child_name("content");
|
||||
this.info_bar.set_revealed(true);
|
||||
|
|
@ -66,11 +75,18 @@ impl Screen<(), LoginData> for LoginDialog {
|
|||
register_button.connect_clicked(clone!(@weak this => move |_| {
|
||||
spawn!(@clone this, async move {
|
||||
if let Some(data) = push!(this.handle, RegisterDialog).await {
|
||||
this.handle.pop(Some(data));
|
||||
this.handle.pop(Some(Some(data)));
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
logout_button.connect_clicked(clone!(@weak this => move |_| {
|
||||
spawn!(@clone this, async move {
|
||||
this.handle.backend.set_login_data(None).await;
|
||||
this.handle.pop(Some(None));
|
||||
});
|
||||
}));
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,8 +96,12 @@ impl Preferences {
|
|||
window.set_transient_for(&this.window);
|
||||
|
||||
spawn!(@clone this, async move {
|
||||
if let Some(data) = replace!(window.navigator, LoginDialog).await {
|
||||
this.login_row.set_subtitle(Some(&data.username));
|
||||
if let Some(data) = replace!(window.navigator, LoginDialog, this.backend.get_login_data()).await {
|
||||
if let Some(data) = data {
|
||||
this.login_row.set_subtitle(Some(&data.username));
|
||||
} else {
|
||||
this.login_row.set_subtitle(Some(&gettext("Not logged in")));
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ impl Backend {
|
|||
}
|
||||
|
||||
match Self::load_login_data().await {
|
||||
Ok(Some(data)) => self.client.set_login_data(data),
|
||||
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),
|
||||
_ => (),
|
||||
|
|
@ -129,11 +129,19 @@ impl Backend {
|
|||
}
|
||||
|
||||
/// Set the user credentials to use.
|
||||
pub async fn set_login_data(&self, data: LoginData) {
|
||||
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);
|
||||
pub async fn set_login_data(&self, data: Option<LoginData>) {
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,13 @@ impl Backend {
|
|||
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)?;
|
||||
|
|
@ -52,7 +59,7 @@ impl Backend {
|
|||
let collection = Self::get_collection(&ss)?;
|
||||
|
||||
let key = "musicus-login-data";
|
||||
Self::delete_secrets(&collection, key)?;
|
||||
Self::delete_secrets_for_key(&collection, key)?;
|
||||
|
||||
let mut attributes = HashMap::new();
|
||||
attributes.insert("username", data.username.as_str());
|
||||
|
|
@ -61,8 +68,19 @@ impl Backend {
|
|||
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(collection: &Collection, key: &str) -> Result<()> {
|
||||
fn delete_secrets_for_key(collection: &Collection, key: &str) -> Result<()> {
|
||||
let items = collection.get_all_items()?;
|
||||
|
||||
for item in items {
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@ impl Client {
|
|||
}
|
||||
|
||||
/// Set the user credentials to use.
|
||||
pub fn set_login_data(&self, data: LoginData) {
|
||||
self.login_data.replace(Some(data));
|
||||
pub fn set_login_data(&self, data: Option<LoginData>) {
|
||||
self.login_data.replace(data);
|
||||
self.token.replace(None);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,29 +100,74 @@
|
|||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Create a new account</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
<object class="GtkBox" id="register_box">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Create a new account</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<property name="valign">start</property>
|
||||
<child>
|
||||
<object class="GtkListBox">
|
||||
<property name="selection-mode">none</property>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="activatable">True</property>
|
||||
<property name="title" translatable="yes">Register a new account</property>
|
||||
<property name="activatable-widget">register_button</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="register_button">
|
||||
<property name="label" translatable="yes">Start</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<property name="valign">start</property>
|
||||
<object class="GtkBox" id="logout_box">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">12</property>
|
||||
<property name="visible">false</property>
|
||||
<child>
|
||||
<object class="GtkListBox">
|
||||
<property name="selection-mode">none</property>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Logout</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<property name="valign">start</property>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="activatable">True</property>
|
||||
<property name="title" translatable="yes">Register a new account</property>
|
||||
<property name="activatable-widget">register_button</property>
|
||||
<object class="GtkListBox">
|
||||
<property name="selection-mode">none</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="register_button">
|
||||
<property name="label" translatable="yes">Start</property>
|
||||
<property name="valign">center</property>
|
||||
<object class="AdwActionRow">
|
||||
<property name="activatable">True</property>
|
||||
<property name="title" translatable="yes">Don't use an account</property>
|
||||
<property name="activatable-widget">logout_button</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="logout_button">
|
||||
<property name="label" translatable="yes">Logout</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue