Partially handle errors

This commit is contained in:
Jeremy Soller 2023-10-04 11:59:34 -06:00
parent 76b9e8b7bf
commit 3bc299859f
No known key found for this signature in database
GPG key ID: DCFCA852D3906975
2 changed files with 107 additions and 100 deletions

View file

@ -1,4 +1,4 @@
use greetd_ipc::{codec::SyncCodec, AuthMessageType, Request, Response}; use greetd_ipc::{codec::SyncCodec, AuthMessageType, ErrorType, Request, Response};
use std::io; use std::io;
use tokio::net::UnixListener; use tokio::net::UnixListener;
@ -40,7 +40,15 @@ async fn main() {
auth_message_type: AuthMessageType::Secret, auth_message_type: AuthMessageType::Secret,
auth_message: "Password:".to_string(), auth_message: "Password:".to_string(),
}, },
Request::PostAuthMessageResponse { .. } => Response::Success, Request::PostAuthMessageResponse { response } => {
match response.as_ref().map(|x| x.as_str()) {
Some("password") => Response::Success,
_ => Response::Error {
error_type: ErrorType::AuthError,
description: "pam_authenticate: AUTH_ERR".to_string(),
},
}
}
Request::StartSession { .. } => Response::Success, Request::StartSession { .. } => Response::Success,
_ => { _ => {
println!("unhandled request"); println!("unhandled request");

View file

@ -154,7 +154,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
Ok(()) Ok(())
} }
async fn request(socket: Arc<UnixStream>, request: Request) -> Message { async fn request_message(socket: Arc<UnixStream>, request: Request) -> Message {
//TODO: handle errors //TODO: handle errors
socket.writable().await.unwrap(); socket.writable().await.unwrap();
{ {
@ -181,28 +181,42 @@ async fn request(socket: Arc<UnixStream>, request: Request) -> Message {
} => match auth_message_type { } => match auth_message_type {
AuthMessageType::Secret => { AuthMessageType::Secret => {
return Message::Input(InputState::Auth { return Message::Input(InputState::Auth {
secret: true,
prompt: auth_message, prompt: auth_message,
value: String::new(), value_opt: Some(String::new()),
secret: true,
}) })
} }
AuthMessageType::Visible => { AuthMessageType::Visible => {
return Message::Input(InputState::Auth { return Message::Input(InputState::Auth {
secret: false,
prompt: auth_message, prompt: auth_message,
value: String::new(), value_opt: Some(String::new()),
secret: false,
})
}
//TODO: treat error type differently?
AuthMessageType::Info | AuthMessageType::Error => {
return Message::Input(InputState::Auth {
prompt: auth_message,
value_opt: None,
secret: false,
}) })
} }
_ => todo!("unsupported auth_message_type {:?}", auth_message_type),
}, },
Response::Error {
error_type: _,
description,
} => {
//TODO: use error_type?
return Message::Error(description);
}
Response::Success => match request { Response::Success => match request {
Request::CreateSession { .. } => { Request::CreateSession { .. } => {
// User has no auth required, proceed to login // User has no auth required, proceed to login
return Message::Login; return Message::Login(socket);
} }
Request::PostAuthMessageResponse { .. } => { Request::PostAuthMessageResponse { .. } => {
// All auth is completed, proceed to login // All auth is completed, proceed to login
return Message::Login; return Message::Login(socket);
} }
Request::StartSession { .. } => { Request::StartSession { .. } => {
// Session has been started, exit greeter // Session has been started, exit greeter
@ -213,10 +227,6 @@ async fn request(socket: Arc<UnixStream>, request: Request) -> Message {
return Message::None; return Message::None;
} }
}, },
_ => {
log::error!("unhandled response");
break;
}
} }
} }
Err(err) => match err.kind() { Err(err) => match err.kind() {
@ -232,6 +242,13 @@ async fn request(socket: Arc<UnixStream>, request: Request) -> Message {
Message::None Message::None
} }
fn request_command(socket: Arc<UnixStream>, request: Request) -> Command<Message> {
Command::perform(
async move { message::app(request_message(socket, request).await) },
|x| x,
)
}
#[derive(Clone)] #[derive(Clone)]
pub struct Flags { pub struct Flags {
users: Vec<(pwd::Passwd, Option<widget::image::Handle>)>, users: Vec<(pwd::Passwd, Option<widget::image::Handle>)>,
@ -255,9 +272,9 @@ pub enum InputState {
None, None,
Username, Username,
Auth { Auth {
secret: bool,
prompt: String, prompt: String,
value: String, value_opt: Option<String>,
secret: bool,
}, },
} }
@ -268,9 +285,10 @@ pub enum Message {
Socket(SocketState), Socket(SocketState),
Input(InputState), Input(InputState),
Session(String), Session(String),
Username(String), Error(String),
Auth(String), Username(Arc<UnixStream>, String),
Login, Auth(Arc<UnixStream>, Option<String>),
Login(Arc<UnixStream>),
Exit, Exit,
} }
@ -278,10 +296,11 @@ pub enum Message {
pub struct App { pub struct App {
core: Core, core: Core,
flags: Flags, flags: Flags,
session_names: Vec<String>,
selected_session: String,
socket_state: SocketState, socket_state: SocketState,
input_state: InputState, input_state: InputState,
session_names: Vec<String>,
selected_session: String,
error_opt: Option<String>,
text_input_id: widget::Id, text_input_id: widget::Id,
} }
@ -326,11 +345,12 @@ impl cosmic::Application for App {
App { App {
core, core,
flags, flags,
session_names,
selected_session,
socket_state: SocketState::Pending, socket_state: SocketState::Pending,
//TODO: set to pending until socket is open? //TODO: set to pending until socket is open?
input_state: InputState::Username, input_state: InputState::Username,
session_names,
selected_session,
error_opt: None,
text_input_id: widget::Id::unique(), text_input_id: widget::Id::unique(),
}, },
Command::perform( Command::perform(
@ -363,66 +383,29 @@ impl cosmic::Application for App {
Message::Session(selected_session) => { Message::Session(selected_session) => {
self.selected_session = selected_session; self.selected_session = selected_session;
} }
Message::Username(username) => match &self.socket_state { Message::Error(error) => {
SocketState::Open(socket) => { self.error_opt = Some(error);
let socket = socket.clone(); }
let username = username.clone(); Message::Username(socket, username) => {
return Command::perform( return request_command(socket, Request::CreateSession { username });
async move { }
message::app(request(socket, Request::CreateSession { username }).await) Message::Auth(socket, response) => {
}, return request_command(socket, Request::PostAuthMessageResponse { response });
|x| x, }
); Message::Login(socket) => {
} match self.flags.sessions.get(&self.selected_session).cloned() {
_ => todo!("socket not open but username provided"), Some(cmd) => {
}, return request_command(
Message::Auth(value) => match &self.socket_state { socket,
SocketState::Open(socket) => { Request::StartSession {
let socket = socket.clone(); cmd,
let value = value.clone(); env: Vec::new(),
return Command::perform( },
async move { );
message::app(
request(
socket,
Request::PostAuthMessageResponse {
response: Some(value),
},
)
.await,
)
},
|x| x,
);
}
_ => todo!("socket not open but authentication provided"),
},
Message::Login => match &self.socket_state {
SocketState::Open(socket) => {
match self.flags.sessions.get(&self.selected_session).cloned() {
Some(cmd) => {
let socket = socket.clone();
return Command::perform(
async move {
message::app(
request(
socket,
Request::StartSession {
cmd,
env: Vec::new(),
},
)
.await,
)
},
|x| x,
);
}
None => todo!("session {:?} not found", self.selected_session),
} }
None => todo!("session {:?} not found", self.selected_session),
} }
_ => todo!("socket not open but attempting to log in"), }
},
Message::Exit => { Message::Exit => {
return iced::window::close(); return iced::window::close();
} }
@ -434,7 +417,7 @@ impl cosmic::Application for App {
fn view(&self) -> Element<Self::Message> { fn view(&self) -> Element<Self::Message> {
let content: Element<_> = match &self.socket_state { let content: Element<_> = match &self.socket_state {
SocketState::Pending => widget::text("Opening GREETD_SOCK").into(), SocketState::Pending => widget::text("Opening GREETD_SOCK").into(),
SocketState::Open(_) => match &self.input_state { SocketState::Open(socket) => match &self.input_state {
InputState::None => { InputState::None => {
//TODO //TODO
widget::text("").into() widget::text("").into()
@ -466,35 +449,47 @@ impl cosmic::Application for App {
.padding(16) .padding(16)
.style(cosmic::theme::Container::Primary), .style(cosmic::theme::Container::Primary),
) )
.on_press(Message::Username(user.name.clone())), .on_press(Message::Username(socket.clone(), user.name.clone())),
); );
} }
row.into() row.into()
} }
InputState::Auth { InputState::Auth {
secret,
prompt, prompt,
value, value_opt,
secret,
} => { } => {
let mut column = widget::column::with_capacity(2) let mut column = widget::column::with_capacity(2)
.spacing(12.0) .spacing(12.0)
.width(iced::Length::Fixed(400.0)); .width(iced::Length::Fixed(400.0));
column = column.push(widget::text(prompt)); column = column.push(widget::text(prompt));
let text_input = widget::text_input("", &value)
.id(self.text_input_id.clone()) match value_opt {
.on_input(|value| { Some(value) => {
Message::Input(InputState::Auth { let text_input = widget::text_input("", &value)
secret: *secret, .id(self.text_input_id.clone())
prompt: prompt.clone(), .on_input(|value| {
value, Message::Input(InputState::Auth {
}) prompt: prompt.clone(),
}) value_opt: Some(value),
.on_submit(Message::Auth(value.clone())); secret: *secret,
if *secret { })
column = column.push(text_input.password()); })
} else { .on_submit(Message::Auth(socket.clone(), Some(value.clone())));
column = column.push(text_input); if *secret {
column = column.push(text_input.password());
} else {
column = column.push(text_input);
}
}
None => {
column = column.push(
widget::button("Confirm")
.on_press(Message::Auth(socket.clone(), None)),
);
}
} }
column.into() column.into()
} }
}, },
@ -510,11 +505,15 @@ impl cosmic::Application for App {
Message::Session, Message::Session,
); );
let column = widget::column::with_capacity(2) let mut column = widget::column::with_capacity(3)
.push(content) .push(content)
.push(session_picker) .push(session_picker)
.spacing(12.0); .spacing(12.0);
if let Some(error) = &self.error_opt {
column = column.push(widget::text(error.clone()));
}
let centered = widget::container(column) let centered = widget::container(column)
.width(iced::Length::Fill) .width(iced::Length::Fill)
.height(iced::Length::Fill) .height(iced::Length::Fill)