first pass of merging in warp (doesn't build)
This commit is contained in:
@@ -548,8 +548,6 @@ pub fn install_root_tmux_script(
|
||||
app: &AppContext,
|
||||
can_run_sudo: bool,
|
||||
) -> Option<String> {
|
||||
use asset_macro::bundled_asset;
|
||||
use galaxyui::assets::asset_cache::{AssetCache, AssetState};
|
||||
|
||||
let asset_source = match (
|
||||
system.operating_system.as_str(),
|
||||
|
||||
@@ -1,10 +1 @@
|
||||
use std::time::Duration;
|
||||
|
||||
pub mod error;
|
||||
pub mod install_tmux;
|
||||
pub mod root_access;
|
||||
pub mod ssh_detection;
|
||||
pub mod util;
|
||||
pub mod warpify;
|
||||
|
||||
pub const SSH_WARPIFY_TIMEOUT_DURATION: Duration = Duration::from_secs(8);
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(untagged, rename_all = "snake_case")]
|
||||
pub enum RootAccess {
|
||||
IsRoot,
|
||||
CanRunSudo,
|
||||
#[default]
|
||||
NoRootAccess,
|
||||
}
|
||||
|
||||
impl FromStr for RootAccess {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||
match input {
|
||||
"is_root" => Ok(RootAccess::IsRoot),
|
||||
"can_run_sudo" => Ok(RootAccess::CanRunSudo),
|
||||
"no_root_access" => Ok(RootAccess::NoRootAccess),
|
||||
_ => Err(anyhow::anyhow!("Invalid RootAccess")),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,7 +127,7 @@ impl InteractiveSshCommand {
|
||||
|
||||
// Otherwise, it's a positional argument (e.g., hostname, command to run)
|
||||
pos_arg => {
|
||||
// If we detect mutliple positional args, there's some type of unknown command formulation.
|
||||
// If we detect multiple positional args, there's some type of unknown command formulation.
|
||||
if host.is_some() {
|
||||
return None;
|
||||
}
|
||||
@@ -147,11 +147,9 @@ pub enum SshLikeCommand {
|
||||
DigitalOceanDroplet,
|
||||
}
|
||||
|
||||
/// TMUX SSH Warpification can be triggered by any command that
|
||||
/// we determine to be an interactive SSH command. This enum
|
||||
/// represents the different types of SSH commands we support
|
||||
/// for TMUX Warpification. `Ssh` means a literal `ssh` command,
|
||||
/// where all other commands are categorized as SSH-like commands.
|
||||
/// Represents the different kinds of commands we recognize as starting an interactive SSH
|
||||
/// session. `Ssh` means a literal `ssh` command, where all other commands (e.g. `gcloud
|
||||
/// compute ssh`) are categorized as SSH-like commands.
|
||||
pub enum SshWarpifyCommand {
|
||||
Ssh,
|
||||
SshLike(SshLikeCommand),
|
||||
@@ -159,7 +157,7 @@ pub enum SshWarpifyCommand {
|
||||
|
||||
impl SshWarpifyCommand {
|
||||
/// Not a literal `ssh` command, but another command that starts an interactive SSH
|
||||
/// session that we can Warpify with TMUX.
|
||||
/// session.
|
||||
pub fn is_ssh_like_command(&self) -> bool {
|
||||
matches!(self, SshWarpifyCommand::SshLike(_))
|
||||
}
|
||||
@@ -272,145 +270,5 @@ pub fn transfer_file_sftp_command(
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn ssh_gcloud_ssh_parsing() {
|
||||
assert!(parse_interactive_ssh_command("gcloud").is_none());
|
||||
assert!(parse_interactive_ssh_command("gcloud compute").is_none());
|
||||
assert!(parse_interactive_ssh_command("gcloud compute ss").is_none());
|
||||
assert!(parse_interactive_ssh_command("gcloud compute ssh").is_none());
|
||||
assert!(parse_interactive_ssh_command("command gcloud compute ssh").is_none());
|
||||
|
||||
assert!(
|
||||
parse_interactive_ssh_command("command gcloud compute ssh --zone us-west1-a").is_some()
|
||||
);
|
||||
assert!(parse_interactive_ssh_command("gcloud compute ssh --zone us-west1-a").is_some());
|
||||
assert!(
|
||||
parse_interactive_ssh_command("gcloud compute ssh --zone us-west1-a my-instance")
|
||||
.is_some()
|
||||
);
|
||||
assert!(parse_interactive_ssh_command(
|
||||
"gcloud compute ssh --zone us-west1-a my-instance --project my-project"
|
||||
)
|
||||
.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ssh_elastic_beanstalk_parsing() {
|
||||
assert!(parse_interactive_ssh_command("eb").is_none());
|
||||
assert!(parse_interactive_ssh_command("eb ss").is_none());
|
||||
assert!(parse_interactive_ssh_command("eb ssh").is_none());
|
||||
assert!(parse_interactive_ssh_command("command eb ssh").is_none());
|
||||
|
||||
assert!(parse_interactive_ssh_command("command eb ssh --profile my-profile").is_some());
|
||||
assert!(parse_interactive_ssh_command("eb ssh --profile my-profile").is_some());
|
||||
assert!(parse_interactive_ssh_command("eb ssh --profile my-profile my-env").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ssh_digital_ocean_droplet_parsing() {
|
||||
assert!(parse_interactive_ssh_command("doctl").is_none());
|
||||
assert!(parse_interactive_ssh_command("doctl compute").is_none());
|
||||
assert!(parse_interactive_ssh_command("doctl compute ss").is_none());
|
||||
assert!(parse_interactive_ssh_command("doctl compute ssh").is_none());
|
||||
assert!(parse_interactive_ssh_command("command doctl compute ssh").is_none());
|
||||
|
||||
assert!(parse_interactive_ssh_command("command doctl compute ssh --region nyc1").is_some());
|
||||
assert!(parse_interactive_ssh_command("doctl compute ssh --region nyc1").is_some());
|
||||
assert!(
|
||||
parse_interactive_ssh_command("doctl compute ssh --region nyc1 my-droplet").is_some()
|
||||
);
|
||||
}
|
||||
|
||||
/// Verifies that commands resulting from shell alias expansion are correctly
|
||||
/// detected as interactive SSH commands. When a user types an alias (e.g.
|
||||
/// `myssh`), the terminal view expands it to the alias value before passing
|
||||
/// it to `parse_interactive_ssh_command`. These tests cover representative
|
||||
/// expanded forms.
|
||||
#[test]
|
||||
fn ssh_alias_expanded_commands() {
|
||||
// Simple alias: alias myssh='ssh user@host'
|
||||
assert_eq!(
|
||||
parse_interactive_ssh_command("ssh user@host").unwrap().host,
|
||||
Some("user@host".to_string())
|
||||
);
|
||||
|
||||
// Alias with key and user: alias company1='ssh -i /path/to/key user@server'
|
||||
assert_eq!(
|
||||
parse_interactive_ssh_command("ssh -i /path/to/key user@server")
|
||||
.unwrap()
|
||||
.host,
|
||||
Some("user@server".to_string())
|
||||
);
|
||||
|
||||
// Alias with extra args appended by the user: alias myssh='ssh -i key'
|
||||
// then the user types `myssh user@host` which expands to `ssh -i key user@host`
|
||||
assert_eq!(
|
||||
parse_interactive_ssh_command("ssh -i key user@host")
|
||||
.unwrap()
|
||||
.host,
|
||||
Some("user@host".to_string())
|
||||
);
|
||||
|
||||
// Alias that isn't SSH should not match
|
||||
assert!(parse_interactive_ssh_command("ls -la").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ssh_interactive_shell_parsing() {
|
||||
assert!(parse_interactive_ssh_command("").is_none());
|
||||
assert!(parse_interactive_ssh_command("ls").is_none());
|
||||
assert!(parse_interactive_ssh_command("ssh-add-key").is_none());
|
||||
|
||||
// Basic interactive command
|
||||
assert!(
|
||||
parse_interactive_ssh_command("ssh localhost").unwrap().host
|
||||
== Some("localhost".to_string())
|
||||
);
|
||||
assert!(
|
||||
parse_interactive_ssh_command("command ssh localhost")
|
||||
.unwrap()
|
||||
.host
|
||||
== Some("localhost".to_string())
|
||||
);
|
||||
assert!(
|
||||
parse_interactive_ssh_command("ssh root@127.14.80.1 -p 2222")
|
||||
.unwrap()
|
||||
.host
|
||||
== Some("root@127.14.80.1".to_string())
|
||||
);
|
||||
assert!(
|
||||
parse_interactive_ssh_command("ssh -4vw root@127.14.80.1 -p 2222")
|
||||
.unwrap()
|
||||
.host
|
||||
== Some("root@127.14.80.1".to_string())
|
||||
);
|
||||
|
||||
// Commands with -T or -W, which are non-interactive
|
||||
assert!(parse_interactive_ssh_command("ssh -T user@host").is_none());
|
||||
assert!(parse_interactive_ssh_command("ssh -v user@host -W localhost:22").is_none());
|
||||
assert!(
|
||||
parse_interactive_ssh_command("ssh -o IdentityFile=/etc/file -T user@host").is_none()
|
||||
);
|
||||
|
||||
// Commands with multiple positional arguments, implying non-interactive
|
||||
assert!(parse_interactive_ssh_command("ssh user@host ls").is_none());
|
||||
assert!(parse_interactive_ssh_command("ssh user@host echo 'Hello, World!'").is_none());
|
||||
|
||||
// Weird spacing and shell characters shouldn't matter
|
||||
assert!(
|
||||
parse_interactive_ssh_command("ssh user@host")
|
||||
.unwrap()
|
||||
.host
|
||||
== Some("user@host".to_string())
|
||||
);
|
||||
assert!(
|
||||
parse_interactive_ssh_command("ssh -4 -- localhost")
|
||||
.unwrap()
|
||||
.host
|
||||
== Some("localhost".to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
#[path = "util_tests.rs"]
|
||||
mod tests;
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn ssh_gcloud_ssh_parsing() {
|
||||
assert!(parse_interactive_ssh_command("gcloud").is_none());
|
||||
assert!(parse_interactive_ssh_command("gcloud compute").is_none());
|
||||
assert!(parse_interactive_ssh_command("gcloud compute ss").is_none());
|
||||
assert!(parse_interactive_ssh_command("gcloud compute ssh").is_none());
|
||||
assert!(parse_interactive_ssh_command("command gcloud compute ssh").is_none());
|
||||
|
||||
assert!(
|
||||
parse_interactive_ssh_command("command gcloud compute ssh --zone us-west1-a").is_some()
|
||||
);
|
||||
assert!(parse_interactive_ssh_command("gcloud compute ssh --zone us-west1-a").is_some());
|
||||
assert!(
|
||||
parse_interactive_ssh_command("gcloud compute ssh --zone us-west1-a my-instance").is_some()
|
||||
);
|
||||
assert!(parse_interactive_ssh_command(
|
||||
"gcloud compute ssh --zone us-west1-a my-instance --project my-project"
|
||||
)
|
||||
.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ssh_elastic_beanstalk_parsing() {
|
||||
assert!(parse_interactive_ssh_command("eb").is_none());
|
||||
assert!(parse_interactive_ssh_command("eb ss").is_none());
|
||||
assert!(parse_interactive_ssh_command("eb ssh").is_none());
|
||||
assert!(parse_interactive_ssh_command("command eb ssh").is_none());
|
||||
|
||||
assert!(parse_interactive_ssh_command("command eb ssh --profile my-profile").is_some());
|
||||
assert!(parse_interactive_ssh_command("eb ssh --profile my-profile").is_some());
|
||||
assert!(parse_interactive_ssh_command("eb ssh --profile my-profile my-env").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ssh_digital_ocean_droplet_parsing() {
|
||||
assert!(parse_interactive_ssh_command("doctl").is_none());
|
||||
assert!(parse_interactive_ssh_command("doctl compute").is_none());
|
||||
assert!(parse_interactive_ssh_command("doctl compute ss").is_none());
|
||||
assert!(parse_interactive_ssh_command("doctl compute ssh").is_none());
|
||||
assert!(parse_interactive_ssh_command("command doctl compute ssh").is_none());
|
||||
|
||||
assert!(parse_interactive_ssh_command("command doctl compute ssh --region nyc1").is_some());
|
||||
assert!(parse_interactive_ssh_command("doctl compute ssh --region nyc1").is_some());
|
||||
assert!(parse_interactive_ssh_command("doctl compute ssh --region nyc1 my-droplet").is_some());
|
||||
}
|
||||
|
||||
/// Verifies that commands resulting from shell alias expansion are correctly
|
||||
/// detected as interactive SSH commands. When a user types an alias (e.g.
|
||||
/// `myssh`), the terminal view expands it to the alias value before passing
|
||||
/// it to `parse_interactive_ssh_command`. These tests cover representative
|
||||
/// expanded forms.
|
||||
#[test]
|
||||
fn ssh_alias_expanded_commands() {
|
||||
// Simple alias: alias myssh='ssh user@host'
|
||||
assert_eq!(
|
||||
parse_interactive_ssh_command("ssh user@host").unwrap().host,
|
||||
Some("user@host".to_string())
|
||||
);
|
||||
|
||||
// Alias with key and user: alias company1='ssh -i /path/to/key user@server'
|
||||
assert_eq!(
|
||||
parse_interactive_ssh_command("ssh -i /path/to/key user@server")
|
||||
.unwrap()
|
||||
.host,
|
||||
Some("user@server".to_string())
|
||||
);
|
||||
|
||||
// Alias with extra args appended by the user: alias myssh='ssh -i key'
|
||||
// then the user types `myssh user@host` which expands to `ssh -i key user@host`
|
||||
assert_eq!(
|
||||
parse_interactive_ssh_command("ssh -i key user@host")
|
||||
.unwrap()
|
||||
.host,
|
||||
Some("user@host".to_string())
|
||||
);
|
||||
|
||||
// Alias that isn't SSH should not match
|
||||
assert!(parse_interactive_ssh_command("ls -la").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ssh_interactive_shell_parsing() {
|
||||
assert!(parse_interactive_ssh_command("").is_none());
|
||||
assert!(parse_interactive_ssh_command("ls").is_none());
|
||||
assert!(parse_interactive_ssh_command("ssh-add-key").is_none());
|
||||
|
||||
// Basic interactive command
|
||||
assert!(
|
||||
parse_interactive_ssh_command("ssh localhost").unwrap().host
|
||||
== Some("localhost".to_string())
|
||||
);
|
||||
assert!(
|
||||
parse_interactive_ssh_command("command ssh localhost")
|
||||
.unwrap()
|
||||
.host
|
||||
== Some("localhost".to_string())
|
||||
);
|
||||
assert!(
|
||||
parse_interactive_ssh_command("ssh root@127.14.80.1 -p 2222")
|
||||
.unwrap()
|
||||
.host
|
||||
== Some("root@127.14.80.1".to_string())
|
||||
);
|
||||
assert!(
|
||||
parse_interactive_ssh_command("ssh -4vw root@127.14.80.1 -p 2222")
|
||||
.unwrap()
|
||||
.host
|
||||
== Some("root@127.14.80.1".to_string())
|
||||
);
|
||||
|
||||
// Commands with -T or -W, which are non-interactive
|
||||
assert!(parse_interactive_ssh_command("ssh -T user@host").is_none());
|
||||
assert!(parse_interactive_ssh_command("ssh -v user@host -W localhost:22").is_none());
|
||||
assert!(parse_interactive_ssh_command("ssh -o IdentityFile=/etc/file -T user@host").is_none());
|
||||
|
||||
// Commands with multiple positional arguments, implying non-interactive
|
||||
assert!(parse_interactive_ssh_command("ssh user@host ls").is_none());
|
||||
assert!(parse_interactive_ssh_command("ssh user@host echo 'Hello, World!'").is_none());
|
||||
|
||||
// Weird spacing and shell characters shouldn't matter
|
||||
assert!(
|
||||
parse_interactive_ssh_command("ssh user@host")
|
||||
.unwrap()
|
||||
.host
|
||||
== Some("user@host".to_string())
|
||||
);
|
||||
assert!(
|
||||
parse_interactive_ssh_command("ssh -4 -- localhost")
|
||||
.unwrap()
|
||||
.host
|
||||
== Some("localhost".to_string())
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user