Files
authforge/gui/src/error.rs

88 lines
3.0 KiB
Rust

//! 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"));
}
}