feat(gui): error helper to classify zbus errors and produce user messages
This commit is contained in:
87
gui/src/error.rs
Normal file
87
gui/src/error.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
//! Map zbus errors to short, user-facing strings. The GUI surfaces these in
|
||||
//! `adw::Toast` and inside the touch-prompt dialog's failure state.
|
||||
//!
|
||||
//! Pure logic; testable without a display server.
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[allow(dead_code)] // wired through keys_page.rs / enroll_dialog.rs in Tasks 4-6.
|
||||
pub(crate) enum ErrorKind {
|
||||
/// Daemon unreachable / bus dropped — caller should swap to disconnected banner.
|
||||
Disconnected,
|
||||
/// polkit denied. Daemon's message is usually fine to show verbatim.
|
||||
AccessDenied,
|
||||
/// Anything else — daemon returned a typed `Failed(msg)` or similar.
|
||||
Other,
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // wired through keys_page.rs / enroll_dialog.rs in Tasks 4-6.
|
||||
pub(crate) fn classify(err: &zbus::Error) -> ErrorKind {
|
||||
match err {
|
||||
zbus::Error::InputOutput(_) | zbus::Error::Address(_) | zbus::Error::Handshake(_) => {
|
||||
ErrorKind::Disconnected
|
||||
}
|
||||
zbus::Error::FDO(boxed) => match boxed.as_ref() {
|
||||
zbus::fdo::Error::AccessDenied(_) => ErrorKind::AccessDenied,
|
||||
zbus::fdo::Error::ServiceUnknown(_) | zbus::fdo::Error::NameHasNoOwner(_) => {
|
||||
ErrorKind::Disconnected
|
||||
}
|
||||
_ => ErrorKind::Other,
|
||||
},
|
||||
_ => ErrorKind::Other,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // wired through keys_page.rs / enroll_dialog.rs in Tasks 4-6.
|
||||
pub(crate) fn user_message(err: &zbus::Error) -> String {
|
||||
match classify(err) {
|
||||
ErrorKind::Disconnected => {
|
||||
"Couldn't reach the authentication daemon. Make sure authforge-daemon is running."
|
||||
.to_string()
|
||||
}
|
||||
ErrorKind::AccessDenied => match err {
|
||||
zbus::Error::FDO(boxed) => match boxed.as_ref() {
|
||||
zbus::fdo::Error::AccessDenied(msg) => msg.clone(),
|
||||
_ => "Access denied.".to_string(),
|
||||
},
|
||||
_ => "Access denied.".to_string(),
|
||||
},
|
||||
ErrorKind::Other => err.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn service_unknown_classifies_as_disconnected() {
|
||||
let e = zbus::Error::FDO(Box::new(zbus::fdo::Error::ServiceUnknown(
|
||||
"no daemon".to_string(),
|
||||
)));
|
||||
assert_eq!(classify(&e), ErrorKind::Disconnected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn access_denied_classifies_as_access_denied() {
|
||||
let e = zbus::Error::FDO(Box::new(zbus::fdo::Error::AccessDenied(
|
||||
"polkit said no".to_string(),
|
||||
)));
|
||||
assert_eq!(classify(&e), ErrorKind::AccessDenied);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn access_denied_user_message_is_daemon_message_verbatim() {
|
||||
let e = zbus::Error::FDO(Box::new(zbus::fdo::Error::AccessDenied(
|
||||
"polkit said no".to_string(),
|
||||
)));
|
||||
assert_eq!(user_message(&e), "polkit said no");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disconnected_user_message_mentions_authforge_daemon() {
|
||||
let e = zbus::Error::FDO(Box::new(zbus::fdo::Error::ServiceUnknown(
|
||||
"no daemon".to_string(),
|
||||
)));
|
||||
assert!(user_message(&e).contains("authforge-daemon"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user