request unlock/credentials when terminal is launched from locked/empty state

This commit is contained in:
2023-09-11 16:00:58 -07:00
parent 8d7b01629d
commit 61d9acc7c6
12 changed files with 145 additions and 22 deletions

View File

@ -7,9 +7,15 @@ use crate::errors::*;
use crate::state::AppState;
pub async fn launch(use_base: bool) -> Result<(), ExecError> {
let state = APP.get().unwrap().state::<AppState>();
// do all this in a block so we don't hold the lock any longer than necessary
pub async fn launch(use_base: bool) -> Result<(), LaunchTerminalError> {
let app = APP.get().unwrap();
let state = app.state::<AppState>();
// register_terminal_request() returns Err if there is another request pending
if state.register_terminal_request().await.is_err() {
return Ok(());
}
let mut cmd = {
let config = state.config.read().await;
let mut cmd = Command::new(&config.terminal.exec);
@ -17,10 +23,38 @@ pub async fn launch(use_base: bool) -> Result<(), ExecError> {
cmd
};
// similarly
// if session is unlocked or empty, wait for credentials from frontend
if !state.is_unlocked().await {
app.emit_all("launch-terminal-request", ())?;
let window = app.get_window("main")
.ok_or(LaunchTerminalError::NoMainWindow)?;
if !window.is_visible()? {
window.unminimize()?;
window.show()?;
}
window.set_focus()?;
let (tx, rx) = tokio::sync::oneshot::channel();
app.once_global("credentials-event", move |e| {
let success = match e.payload() {
Some("\"unlocked\"") | Some("\"entered\"") => true,
_ => false,
};
let _ = tx.send(success);
});
if !rx.await.unwrap_or(false) {
state.unregister_terminal_request().await;
return Ok(()); // request was canceled by user
}
}
// more lock-management
{
let state = APP.get().unwrap().state::<AppState>();
let app_session = state.session.read().await;
// session should really be unlocked at this point, but if the frontend misbehaves
// (i.e. lies about unlocking) we could end up here with a locked session
// this will result in an error popup to the user (see main hotkey handler)
let (base_creds, session_creds) = app_session.try_get()?;
if use_base {
cmd.env("AWS_ACCESS_KEY_ID", &base_creds.access_key_id);
@ -33,11 +67,16 @@ pub async fn launch(use_base: bool) -> Result<(), ExecError> {
}
}
match cmd.spawn() {
let res = match cmd.spawn() {
Ok(_) => Ok(()),
Err(e) if std::io::ErrorKind::NotFound == e.kind() => {
Err(ExecError::NotFound(cmd.get_program().to_owned()))
},
Err(e) => Err(e.into()),
}
Err(e) => Err(ExecError::ExecutionFailed(e)),
};
state.unregister_terminal_request().await;
res?; // ? auto-conversion is more liberal than .into()
Ok(())
}