diff --git a/src-tauri/src/commands/dialog.rs b/src-tauri/src/commands/dialog.rs index ceb812f..5e8edce 100644 --- a/src-tauri/src/commands/dialog.rs +++ b/src-tauri/src/commands/dialog.rs @@ -4,7 +4,7 @@ //! specifically for picking SSH key files. use rfd::FileDialog; -use std::fs; +use std::{fs, path::Path}; /// Opens a file dialog to pick an SSH private key file. /// @@ -18,9 +18,9 @@ use std::fs; /// or an error if the dialog failed to open. #[tauri::command] pub async fn pick_ssh_key_file() -> Result, String> { + // OpenSSH private keys commonly use names like `id_ed25519` with no extension, + // while rfd filters are extension-based and can hide them. let file = FileDialog::new() - .add_filter("SSH Keys", &["pem", "key", "pub", "ppk"]) - .add_filter("All Files", &["*"]) .set_title("Select SSH Private Key") .pick_file(); @@ -85,5 +85,29 @@ pub async fn pick_download_directory() -> Result, String> { /// Returns the file contents as a string, or an error if the file cannot be read. #[tauri::command] pub async fn read_ssh_key_file(path: String) -> Result { - fs::read_to_string(&path).map_err(|e| format!("Failed to read SSH key file: {}", e)) + read_ssh_key_file_content(path) +} + +fn read_ssh_key_file_content(path: impl AsRef) -> Result { + fs::read_to_string(path.as_ref()).map_err(|e| format!("Failed to read SSH key file: {}", e)) +} + +#[cfg(test)] +mod tests { + use super::read_ssh_key_file_content; + + #[test] + fn reads_extensionless_private_key_files() { + let temp_dir = tempfile::tempdir().expect("temp dir should be created"); + let key_path = temp_dir.path().join("id_ed25519"); + let key_content = + "-----BEGIN OPENSSH PRIVATE KEY-----\nkey\n-----END OPENSSH PRIVATE KEY-----\n"; + + std::fs::write(&key_path, key_content).expect("extensionless key should be written"); + + assert_eq!( + read_ssh_key_file_content(&key_path).expect("extensionless key should be read"), + key_content + ); + } }