Skip to content

Commit

Permalink
allow setting custom ssh key from via argument instead of via questio…
Browse files Browse the repository at this point in the history
…n in profile helper
  • Loading branch information
aprxi committed Aug 14, 2024
1 parent 114244a commit 76871a2
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 50 deletions.
2 changes: 1 addition & 1 deletion lumni/src/apps/builtin/llm/prompt/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ pub async fn run_cli(

let db_conn = Arc::new(ConversationDatabase::new(&sqlite_file, None)?);

let mut profile_handler = db_conn.get_profile_handler(None);
if let Some(ref matches) = matches {
let mut profile_handler = db_conn.get_profile_handler(None);
if let Some(db_matches) = matches.subcommand_matches("db") {
return handle_db_subcommand(db_matches, &db_conn).await;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,17 @@ impl UserProfileDbHandler {
pub fn set_encryption_handler(
&mut self,
encryption_handler: Arc<EncryptionHandler>,
) {
) -> Result<(), ApplicationError> {
// if profile is not yet set, return error as we need to know the profile to validate against existing encryption handler
if self.profile_name.is_none() {
return Err(ApplicationError::InvalidInput(
"Profile name is not yet set".to_string(),
));
}

// TODO: for profiles that are already in database, check if encryption handler in database matches the new one, if it does not throw an error as updating encryption handler is not yet supported
self.encryption_handler = Some(encryption_handler);
Ok(())
}

pub async fn export_profile_settings(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ impl UserProfileDbHandler {
) -> Result<(), ApplicationError> {
let has_encryption_handler = self.encryption_handler.is_some();
let mut created_encryption_handler: Option<EncryptionHandler> = None;

let (encryption_key_id, merged_settings) = {
let mut db = self.db.lock().await;
db.process_queue_with_result(|tx| {
Expand Down Expand Up @@ -106,8 +107,8 @@ impl UserProfileDbHandler {
if self.encryption_handler.is_none() {
// Set new encryption handler outside the closure
if let Some(new_encryption_handler) = created_encryption_handler {
self.encryption_handler =
Some(Arc::new(new_encryption_handler));
// use method as it protects against overwriting existing encryption configuration
self.set_encryption_handler(Arc::new(new_encryption_handler))?;
} else {
return Err(ApplicationError::InvalidInput(
"Failed to create encryption handler".to_string(),
Expand Down Expand Up @@ -211,7 +212,8 @@ impl UserProfileDbHandler {
"Failed to load encryption handler".to_string(),
)
})?;
self.encryption_handler = Some(Arc::new(encryption_handler));
// use method as it protects against overwriting existing encryption configuration
self.set_encryption_handler(Arc::new(encryption_handler))?;
}
self.verify_encryption_key_hash(&key_hash)?;
let settings: JsonValue =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ fn create_edit_subcommand() -> Command {
Command::new("edit")
.about("Add a new profile or edit an existing one with guided setup")
.arg(Arg::new("name").help("Name of the profile to edit (optional)"))
.arg(
Arg::new("ssh-key-path")
.long("ssh-key-path")
.help("Custom SSH key path")
.value_name("PATH"),
)
}

fn create_key_subcommand() -> Command {
Expand Down Expand Up @@ -356,7 +362,8 @@ pub async fn handle_profile_subcommand(

Some(("edit", edit_matches)) => {
let profile_name = edit_matches.get_one::<String>("name").cloned();
interactive_profile_edit(db_handler, profile_name).await?;
let custom_ssh_key_path = edit_matches.get_one::<String>("ssh-key-path").cloned();
interactive_profile_edit(db_handler, profile_name, custom_ssh_key_path).await?;
}

Some(("key", key_matches)) => match key_matches.subcommand() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::io::{self, Write};
use std::path::PathBuf;
use std::sync::Arc;

use dirs::home_dir;
use lumni::api::error::ApplicationError;
use serde_json::{json, Map, Value as JsonValue};

Expand All @@ -23,6 +22,7 @@ enum ModelSelection {
pub async fn interactive_profile_edit(
db_handler: &mut UserProfileDbHandler,
profile_name_to_update: Option<String>,
custom_ssh_key_path: Option<String>,
) -> Result<(), ApplicationError> {
println!("Welcome to the profile creation/editing wizard!");

Expand Down Expand Up @@ -99,8 +99,8 @@ pub async fn interactive_profile_edit(
collect_custom_settings(&mut settings)?;
}

if !is_updating && ask_for_custom_ssh_key()? {
setup_custom_encryption(db_handler).await?;
if custom_ssh_key_path.is_some() {
setup_custom_encryption(db_handler, custom_ssh_key_path.as_ref().unwrap()).await?;
}

db_handler
Expand Down Expand Up @@ -504,54 +504,28 @@ fn should_encrypt_value() -> Result<bool, ApplicationError> {
Ok(encrypt.trim().to_lowercase() == "y")
}

fn ask_for_custom_ssh_key() -> Result<bool, ApplicationError> {
print!("Do you want to use a custom SSH key for encryption? (y/N): ");
io::stdout().flush()?;
let mut response = String::new();
io::stdin().read_line(&mut response)?;
Ok(response.trim().to_lowercase() == "y")
}

async fn setup_custom_encryption(
db_handler: &mut UserProfileDbHandler,
custom_ssh_key_path: &str,
) -> Result<(), ApplicationError> {
println!("Setting up custom SSH key for encryption.");

let default_key_path =
home_dir().unwrap_or_default().join(".ssh").join("id_rsa");
let default_key_str = default_key_path.to_str().unwrap_or("~/.ssh/id_rsa");
let key_path = PathBuf::from(custom_ssh_key_path);

loop {
println!("Default SSH key path: {}", default_key_str);
print!("Enter the path to your SSH key (or press Enter for default): ");
io::stdout().flush()?;
let mut key_path = String::new();
io::stdin().read_line(&mut key_path)?;
let key_path = key_path.trim();

let key_path = if key_path.is_empty() {
default_key_path.clone()
} else {
PathBuf::from(key_path)
};

match EncryptionHandler::new_from_path(&key_path) {
Ok(Some(handler)) => {
println!("Custom SSH key registered successfully.");
db_handler.set_encryption_handler(Arc::new(handler));
break;
}
Ok(None) => {
println!(
"Failed to create encryption handler. Please try again \
with a valid SSH key path."
);
}
Err(e) => {
println!("Error registering SSH key: {}. Please try again.", e);
}
match EncryptionHandler::new_from_path(&key_path) {
Ok(Some(handler)) => {
db_handler.set_encryption_handler(Arc::new(handler))?;
}
Ok(None) => {
return Err(ApplicationError::InvalidInput(
"Failed to create encryption handler with the provided SSH key path.".to_string(),
));
}
Err(e) => {
return Err(ApplicationError::InvalidInput(
format!("Error registering SSH key: {}.", e),
));
}
}

Ok(())
}

0 comments on commit 76871a2

Please sign in to comment.