[fractal/fractal-next] auth_dialog: Add AuthError
- From: Julian Sparber <jsparber src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/fractal-next] auth_dialog: Add AuthError
- Date: Mon, 14 Feb 2022 08:52:31 +0000 (UTC)
commit d82b7ed19cb489fc2524bc4c0f82d17059d630f8
Author: Kai A. Hiller <V02460 gmail com>
Date: Sat Feb 12 08:15:28 2022 +0100
auth_dialog: Add AuthError
src/components/auth_dialog.rs | 31 +++++++++++++++-------
src/components/mod.rs | 2 +-
.../account_settings/devices_page/device.rs | 29 +++++++++-----------
.../account_settings/devices_page/device_row.rs | 26 +++++++++++++-----
.../content/verification/session_verification.rs | 14 +++++-----
5 files changed, 60 insertions(+), 42 deletions(-)
---
diff --git a/src/components/auth_dialog.rs b/src/components/auth_dialog.rs
index 04168565..60abf0db 100644
--- a/src/components/auth_dialog.rs
+++ b/src/components/auth_dialog.rs
@@ -64,6 +64,15 @@ impl AuthData {
}
}
+#[derive(Debug)]
+pub enum AuthError {
+ ServerResponse(Box<Error>),
+ MalformedResponse,
+ StageFailed,
+ NoStageToChoose,
+ UserCancelled,
+}
+
mod imp {
use std::cell::RefCell;
@@ -223,7 +232,7 @@ impl AuthDialog {
>(
&self,
callback: FN,
- ) -> Option<Result<Response, Error>> {
+ ) -> Result<Response, AuthError> {
let priv_ = self.imp();
let client = self.session().client();
let mut auth_data = None;
@@ -235,11 +244,11 @@ impl AuthDialog {
let response = handle.await.unwrap();
let uiaa_info: UiaaInfo = match response {
- Ok(result) => return Some(Ok(result)),
+ Ok(result) => return Ok(result),
Err(Error::Http(UiaaError(FromHttpResponseError::Http(ServerError::Known(
UiaaResponse::AuthResponse(uiaa_info),
))))) => uiaa_info,
- Err(error) => return Some(Err(error)),
+ Err(error) => return Err(AuthError::ServerResponse(Box::new(error))),
};
self.show_auth_error(&uiaa_info.auth_error);
@@ -248,12 +257,13 @@ impl AuthDialog {
let flow = uiaa_info
.flows
.iter()
- .find(|flow| flow.stages.starts_with(&uiaa_info.completed))?;
+ .find(|flow| flow.stages.starts_with(&uiaa_info.completed))
+ .ok_or(AuthError::NoStageToChoose)?;
match flow.stages[uiaa_info.completed.len()].as_ref() {
"m.login.password" => {
priv_.stack.set_visible_child_name("m.login.password");
- if self.show_and_wait_for_response().await {
+ if self.show_and_wait_for_response().await.is_ok() {
let user_id = self.session().user().unwrap().user_id().to_string();
let password = priv_.password.text().to_string();
let session = uiaa_info.session;
@@ -277,12 +287,13 @@ impl AuthDialog {
spawn_tokio!(async move { client_clone.homeserver().await })
.await
.unwrap();
+ let first_stage = flow.stages.first();
self.setup_fallback_page(
homeserver.as_str(),
- flow.stages.first()?.as_ref(),
+ first_stage.ok_or(AuthError::NoStageToChoose)?.as_ref(),
&session,
);
- if self.show_and_wait_for_response().await {
+ if self.show_and_wait_for_response().await.is_ok() {
auth_data =
Some(AuthData::FallbackAcknowledgement(FallbackAcknowledgement {
session,
@@ -294,12 +305,12 @@ impl AuthDialog {
}
}
- return None;
+ return Err(AuthError::UserCancelled);
}
}
/// Lets the user complete the current stage.
- async fn show_and_wait_for_response(&self) -> bool {
+ async fn show_and_wait_for_response(&self) -> Result<(), AuthError> {
let (sender, receiver) = futures::channel::oneshot::channel();
let sender = Cell::new(Some(sender));
@@ -315,7 +326,7 @@ impl AuthDialog {
self.disconnect(handler_id);
self.close();
- result
+ result.then(|| ()).ok_or(AuthError::UserCancelled)
}
fn show_auth_error(&self, auth_error: &Option<ErrorBody>) {
diff --git a/src/components/mod.rs b/src/components/mod.rs
index 8e7df87c..7ad75e41 100644
--- a/src/components/mod.rs
+++ b/src/components/mod.rs
@@ -16,7 +16,7 @@ mod video_player_renderer;
pub use self::{
audio_player::AudioPlayer,
- auth_dialog::{AuthData, AuthDialog},
+ auth_dialog::{AuthData, AuthDialog, AuthError},
avatar::Avatar,
badge::Badge,
context_menu_bin::{ContextMenuBin, ContextMenuBinExt, ContextMenuBinImpl},
diff --git a/src/session/account_settings/devices_page/device.rs
b/src/session/account_settings/devices_page/device.rs
index a5075ecc..1a6a30c5 100644
--- a/src/session/account_settings/devices_page/device.rs
+++ b/src/session/account_settings/devices_page/device.rs
@@ -1,5 +1,4 @@
use gtk::{glib, prelude::*, subclass::prelude::*};
-use log::error;
use matrix_sdk::{
encryption::identities::Device as CryptoDevice,
ruma::{
@@ -9,7 +8,10 @@ use matrix_sdk::{
},
};
-use crate::{components::AuthDialog, session::Session};
+use crate::{
+ components::{AuthDialog, AuthError},
+ session::Session,
+};
mod imp {
use glib::object::WeakRef;
@@ -173,16 +175,17 @@ impl Device {
})
}
- /// Delete the `Device`
- ///
- /// Returns `true` for success
- pub async fn delete(&self, transient_for: Option<&impl IsA<gtk::Window>>) -> bool {
+ /// Deletes the `Device`.
+ pub async fn delete(
+ &self,
+ transient_for: Option<&impl IsA<gtk::Window>>,
+ ) -> Result<(), AuthError> {
let session = self.session();
let device_id = self.device_id().to_owned();
let dialog = AuthDialog::new(transient_for, &session);
- let result = dialog
+ dialog
.authenticate(move |client, auth_data| {
let device_id = device_id.clone();
async move {
@@ -196,16 +199,8 @@ impl Device {
}
}
})
- .await;
- match result {
- Some(Ok(_)) => true,
- Some(Err(err)) => {
- // TODO: show error message to the user
- error!("Failed to delete device: {}", err);
- false
- }
- None => false,
- }
+ .await?;
+ Ok(())
}
pub fn is_verified(&self) -> bool {
diff --git a/src/session/account_settings/devices_page/device_row.rs
b/src/session/account_settings/devices_page/device_row.rs
index 3525b58e..e5682af7 100644
--- a/src/session/account_settings/devices_page/device_row.rs
+++ b/src/session/account_settings/devices_page/device_row.rs
@@ -1,8 +1,13 @@
+use adw::{self, prelude::*};
use gettextrs::gettext;
-use gtk::{glib, glib::clone, prelude::*, subclass::prelude::*, CompositeTemplate};
+use gtk::{glib, glib::clone, subclass::prelude::*, CompositeTemplate};
+use log::error;
use super::Device;
-use crate::{components::SpinnerButton, spawn};
+use crate::{
+ components::{AuthError, SpinnerButton},
+ spawn,
+};
mod imp {
use std::cell::RefCell;
@@ -155,12 +160,19 @@ impl DeviceRow {
if let Some(device) = self.device() {
spawn!(clone!(@weak self as obj => async move {
let window: Option<gtk::Window> = obj.root().and_then(|root| root.downcast().ok());
- let success = device.delete(window.as_ref()).await;
- obj.imp().delete_button.set_loading(false);
-
- if success {
- obj.hide();
+ match device.delete(window.as_ref()).await {
+ Ok(_) => obj.hide(),
+ Err(AuthError::UserCancelled) => {},
+ Err(err) => {
+ error!("Failed to delete device {}: {err:?}", device.device_id());
+ if let Some(adw_window) = window.and_then(|w|
w.downcast::<adw::PreferencesWindow>().ok()) {
+ let device_name = device.display_name();
+ let error_message = gettext!("Failed to delete device “{}”", device_name);
+ adw_window.add_toast(&adw::Toast::new(&error_message));
+ }
+ },
}
+ obj.imp().delete_button.set_loading(false);
}));
}
}
diff --git a/src/session/content/verification/session_verification.rs
b/src/session/content/verification/session_verification.rs
index 522c6b4d..3dc72ab0 100644
--- a/src/session/content/verification/session_verification.rs
+++ b/src/session/content/verification/session_verification.rs
@@ -5,7 +5,7 @@ use log::error;
use super::IdentityVerificationWidget;
use crate::{
- components::{AuthDialog, SpinnerButton},
+ components::{AuthDialog, AuthError, SpinnerButton},
session::verification::{IdentityVerification, VerificationState},
spawn, Error, Session, Window,
};
@@ -303,15 +303,15 @@ impl SessionVerification {
let error_message = match result {
- Some(Ok(_)) => None,
- Some(Err(error)) => {
- error!("Failed to bootstrap cross-signing: {}", error);
- Some(gettext("An error occurred during the creation of the encryption keys."))
- },
- None => {
+ Ok(_) => None,
+ Err(AuthError::UserCancelled) => {
error!("Failed to bootstrap cross-signing: User cancelled the authentication");
Some(gettext("You cancelled the authentication needed to create the encryption keys."))
},
+ Err(error) => {
+ error!("Failed to bootstrap cross-signing: {:?}", error);
+ Some(gettext("An error occurred during the creation of the encryption keys."))
+ },
};
if let Some(error_message) = error_message {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]