Skip to content

Commit

Permalink
ssh dir refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
mariotaku committed Nov 22, 2023
1 parent 539aaf4 commit d78a006
Show file tree
Hide file tree
Showing 15 changed files with 140 additions and 50 deletions.
5 changes: 3 additions & 2 deletions src-tauri/src/conn_pool/connection.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::fmt::{Debug, Formatter};
use std::io::Read;
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};
use std::sync::Mutex;
use std::time::Duration;

Expand All @@ -13,7 +14,7 @@ use crate::device_manager::Device;
use crate::error::Error;

impl DeviceConnection {
pub(crate) fn new(device: Device) -> Result<DeviceConnection, Error> {
pub(crate) fn new(device: Device, ssh_dir: Option<&Path>) -> Result<DeviceConnection, Error> {
let kex = vec![
"curve25519-sha256",
"curve25519-sha256@libssh.org",
Expand Down Expand Up @@ -72,7 +73,7 @@ impl DeviceConnection {

if let Some(private_key) = &device.private_key {
let passphrase = device.valid_passphrase();
let priv_key_content = private_key.content()?;
let priv_key_content = private_key.content(ssh_dir)?;
let priv_key = SshKey::from_privkey_base64(&priv_key_content, passphrase.as_deref())?;

if session.userauth_publickey(None, &priv_key)? != AuthStatus::Success {
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/conn_pool/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::device_manager::Device;
use crate::error::Error;
use libssh_rs::Session;
use r2d2::{Pool, PooledConnection};
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use uuid::Uuid;

Expand Down Expand Up @@ -37,4 +38,5 @@ pub struct DeviceConnectionPool {

pub struct DeviceConnectionManager {
device: Device,
ssh_dir: Option<PathBuf>,
}
7 changes: 4 additions & 3 deletions src-tauri/src/conn_pool/pool.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::fmt::Debug;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use std::time::Duration;

Expand All @@ -11,7 +12,7 @@ use crate::device_manager::Device;
use crate::error::Error;

impl DeviceConnectionPool {
pub fn new(device: Device) -> DeviceConnectionPool {
pub fn new(device: Device, ssh_dir: Option<PathBuf>) -> DeviceConnectionPool {
let last_error = Arc::<Mutex<Option<Error>>>::default();
let inner = Pool::<DeviceConnectionManager>::builder()
.min_idle(Some(0))
Expand All @@ -20,7 +21,7 @@ impl DeviceConnectionPool {
.error_handler(Box::new(DeviceConnectionErrorHandler {
last_error: last_error.clone(),
}))
.build_unchecked(DeviceConnectionManager { device });
.build_unchecked(DeviceConnectionManager { device, ssh_dir });
return DeviceConnectionPool { inner, last_error };
}

Expand All @@ -45,7 +46,7 @@ impl ManageConnection for DeviceConnectionManager {
type Error = Error;

fn connect(&self) -> Result<Self::Connection, Self::Error> {
return DeviceConnection::new(self.device.clone());
return DeviceConnection::new(self.device.clone(), self.ssh_dir.as_deref());
}

fn is_valid(&self, _: &mut Self::Connection) -> Result<(), Self::Error> {
Expand Down
15 changes: 1 addition & 14 deletions src-tauri/src/device_manager/io.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::{env, fs};
use std::fs::{create_dir_all, File};
use std::io::{BufReader, BufWriter, ErrorKind};
use std::path::PathBuf;
use std::{env, fs};

use serde_json::Value;
use tauri::api::path::home_dir;

use crate::device_manager::Device;
use crate::error::Error;
Expand Down Expand Up @@ -62,18 +61,6 @@ pub(crate) async fn write(devices: Vec<Device>) -> Result<(), Error> {
.expect("critical failure in app::io::write task");
}

pub(crate) fn ssh_dir() -> Option<PathBuf> {
return home_dir().map(|d| d.join(".ssh"));
}

pub(crate) fn ensure_ssh_dir() -> Result<PathBuf, Error> {
let dir = ssh_dir().ok_or_else(|| Error::bad_config())?;
if !dir.exists() {
create_dir_all(dir.clone())?;
}
return Ok(dir);
}

#[cfg(target_family = "windows")]
fn devices_file_path() -> Result<PathBuf, Error> {
let home = env::var("APPDATA")
Expand Down
26 changes: 19 additions & 7 deletions src-tauri/src/device_manager/manager.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use std::fs;
use std::path::Path;
use std::fs::create_dir_all;
use std::path::{Path, PathBuf};

use libssh_rs::SshKey;
use tokio::fs::{remove_file, File};
use tokio::io::AsyncWriteExt;

use crate::device_manager::io::{ensure_ssh_dir, read, ssh_dir, write};
use crate::device_manager::io::{read, write};
use crate::device_manager::{Device, DeviceManager, PrivateKey};
use crate::error::Error;
use crate::ssh_dir::{GetSshDir, SetSshDir};

impl DeviceManager {
pub async fn list(&self) -> Result<Vec<Device>, Error> {
Expand Down Expand Up @@ -40,7 +42,7 @@ impl DeviceManager {
let path = Path::new(name);
if path.is_absolute() {
let name = String::from(
pathdiff::diff_paths(path, ensure_ssh_dir()?)
pathdiff::diff_paths(path, self.ensure_ssh_dir()?)
.ok_or(Error::NotFound)?
.to_string_lossy(),
);
Expand All @@ -49,7 +51,7 @@ impl DeviceManager {
}
PrivateKey::Data { data } => {
let name = key.name(device.valid_passphrase())?;
let key_path = ensure_ssh_dir()?.join(&name);
let key_path = self.ensure_ssh_dir()?.join(&name);
let mut file = File::create(key_path).await?;
file.write(data.as_bytes()).await?;
device.private_key = Some(PrivateKey::Path { name });
Expand Down Expand Up @@ -80,7 +82,7 @@ impl DeviceManager {
if !name.starts_with("webos_") {
continue;
}
let key_path = ensure_ssh_dir()?.join(name);
let key_path = self.ensure_ssh_dir()?.join(name);
remove_file(key_path).await?;
}
}
Expand Down Expand Up @@ -114,8 +116,7 @@ impl DeviceManager {
let ssh_key_path = if name_path.is_absolute() {
name_path.to_path_buf()
} else {
let ssh_dir = ssh_dir().ok_or_else(|| Error::bad_config())?;
fs::canonicalize(ssh_dir.join(name))?
fs::canonicalize(self.ensure_ssh_dir()?)?
};
return match SshKey::from_privkey_file(ssh_key_path.to_str().unwrap(), Some(passphrase)) {
Ok(_) => Ok(()),
Expand All @@ -127,3 +128,14 @@ impl DeviceManager {
};
}
}
impl GetSshDir for DeviceManager {
fn get_ssh_dir(&self) -> Option<PathBuf> {
return self.ssh_dir.lock().unwrap().clone();
}
}

impl SetSshDir for DeviceManager {
fn set_ssh_dir(&self, dir: PathBuf) {
*self.ssh_dir.lock().unwrap() = Some(dir);
}
}
11 changes: 3 additions & 8 deletions src-tauri/src/device_manager/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::path::PathBuf;
use std::sync::Mutex;

use serde::{Deserialize, Serialize};
Expand All @@ -13,18 +14,12 @@ pub struct DeviceSessionToken {
pub id: Option<String>,
}

#[derive(Default)]
pub struct DeviceManager {
ssh_dir: Mutex<Option<PathBuf>>,
devices: Mutex<Vec<Device>>,
}

impl Default for DeviceManager {
fn default() -> Self {
return DeviceManager {
devices: Mutex::new(Vec::new()),
};
}
}

#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(untagged)]
pub enum PrivateKey {
Expand Down
9 changes: 5 additions & 4 deletions src-tauri/src/device_manager/privkey.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use libssh_rs::{PublicKeyHashType, SshKey};
use std::io::Read;
use std::path::Path;

use libssh_rs::{PublicKeyHashType, SshKey};

use crate::device_manager::io::ssh_dir;
use crate::device_manager::PrivateKey;
use crate::error::Error;

impl PrivateKey {
pub fn content(&self) -> Result<String, Error> {
pub fn content(&self, ssh_dir: Option<&Path>) -> Result<String, Error> {
return match self {
PrivateKey::Path { name } => {
let mut secret_file =
std::fs::File::open(ssh_dir().ok_or(Error::bad_config())?.join(name))?;
std::fs::File::open(ssh_dir.ok_or(Error::bad_config())?.join(name))?;
let mut secret = String::new();
secret_file.read_to_string(&mut secret)?;
Ok(secret)
Expand Down
31 changes: 28 additions & 3 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
extern crate core;

use log::LevelFilter;
use tauri::Manager;
use std::path::PathBuf;

use log::LevelFilter;
use native_dialog::{MessageDialog, MessageType};
use tauri::api::path::home_dir;
use tauri::{AppHandle, Manager, RunEvent, Runtime};

use crate::device_manager::DeviceManager;
use crate::session_manager::SessionManager;
use crate::shell_manager::ShellManager;
use crate::spawn_manager::SpawnManager;
use crate::ssh_dir::{GetSshDir, SetSshDir};

mod conn_pool;
mod device_manager;
Expand All @@ -19,6 +22,7 @@ mod remote_files;
mod session_manager;
mod shell_manager;
mod spawn_manager;
mod ssh_dir;

//#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
Expand Down Expand Up @@ -50,7 +54,20 @@ pub fn run() {
let spawns = wnd.state::<SpawnManager>();
spawns.clear();
})
.run(tauri::generate_context!());
.build(tauri::generate_context!())
.and_then(|app| {
app.run(|app, event| match event {
RunEvent::Ready => {
if let Some(ssh_dir) = app.get_ssh_dir() {
app.state::<DeviceManager>().set_ssh_dir(ssh_dir.clone());
app.state::<SessionManager>().set_ssh_dir(ssh_dir.clone());
app.state::<ShellManager>().set_ssh_dir(ssh_dir.clone());
}
}
_ => {}
});
return Ok(());
});
if let Err(e) = result {
#[cfg(windows)]
if let tauri::Error::Runtime(ref e) = e {
Expand All @@ -72,3 +89,11 @@ pub fn run() {
.expect("Unexpected error occurred while processing unexpected error :(");
}
}

impl<R: Runtime> GetSshDir for AppHandle<R> {
fn get_ssh_dir(&self) -> Option<PathBuf> {
return home_dir()
.or_else(|| self.path_resolver().app_data_dir())
.map(|d| d.join(".ssh"));
}
}
7 changes: 4 additions & 3 deletions src-tauri/src/plugins/device.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use tauri::State;
use tauri::{
plugin::{Builder, TauriPlugin},
Runtime,
};
use tauri::{AppHandle, State};

use crate::device_manager::{Device, DeviceManager};
use crate::error::Error;
use crate::ssh_dir::GetSshDir;

#[tauri::command]
async fn list(manager: State<'_, DeviceManager>) -> Result<Vec<Device>, Error> {
Expand Down Expand Up @@ -57,11 +58,11 @@ async fn localkey_verify(
}

#[tauri::command]
async fn privkey_read(device: Device) -> Result<String, Error> {
async fn privkey_read<R: Runtime>(app: AppHandle<R>, device: Device) -> Result<String, Error> {
return Ok(device
.private_key
.ok_or_else(|| Error::bad_config())?
.content()?);
.content(app.get_ssh_dir().as_deref())?);
}

/// Initializes the plugin.
Expand Down
20 changes: 17 additions & 3 deletions src-tauri/src/session_manager/manager.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::path::PathBuf;
use std::sync::{Arc, Condvar, Mutex};

use crate::conn_pool::{DeviceConnectionPool, ManagedDeviceConnection};
use crate::device_manager::Device;
use crate::error::Error;
use crate::session_manager::{Proc, SessionManager};
use crate::ssh_dir::{GetSshDir, SetSshDir};

impl SessionManager {
pub fn session(&self, device: Device) -> Result<ManagedDeviceConnection, Error> {
Expand Down Expand Up @@ -36,14 +38,14 @@ impl SessionManager {
command: String::from(command),
callback: Mutex::default(),
ready: Arc::new((Mutex::default(), Condvar::new())),
sender:Mutex::default(),
sender: Mutex::default(),
interrupted: Mutex::new(false),
};
}

fn pool(&self, device: Device) -> DeviceConnectionPool {
if device.new {
return DeviceConnectionPool::new(device);
return DeviceConnectionPool::new(device, self.get_ssh_dir());
}
if let Some(p) = self
.pools
Expand All @@ -54,11 +56,23 @@ impl SessionManager {
return p.clone();
}
let key = device.name.clone();
let pool = DeviceConnectionPool::new(device);
let pool = DeviceConnectionPool::new(device, self.get_ssh_dir());
self.pools
.lock()
.expect("Failed to lock SessionManager::pools")
.insert(key, pool.clone());
return pool;
}
}

impl GetSshDir for SessionManager {
fn get_ssh_dir(&self) -> Option<PathBuf> {
return self.ssh_dir.lock().unwrap().clone();
}
}

impl SetSshDir for SessionManager {
fn set_ssh_dir(&self, dir: PathBuf) {
*self.ssh_dir.lock().unwrap() = Some(dir);
}
}
2 changes: 2 additions & 0 deletions src-tauri/src/session_manager/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Condvar, Mutex};

Expand All @@ -12,6 +13,7 @@ mod proc;

#[derive(Default)]
pub struct SessionManager {
ssh_dir: Mutex<Option<PathBuf>>,
pools: Mutex<HashMap<String, DeviceConnectionPool>>,
}

Expand Down
Loading

0 comments on commit d78a006

Please sign in to comment.