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 tokio::net::UnixListener;
@ -40,7 +40,15 @@ async fn main() {
auth_message_type: AuthMessageType::Secret,
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,
_ => {
println!("unhandled request");

View file

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