connect: add export_keys tauri function (#1443)

* connect: tidy

* connect: add export_keys tauri function

* changelog: add note

* connect: remove unused
This commit is contained in:
Jon Häggblad
2022-07-06 14:02:40 +02:00
committed by GitHub
parent 0a4bbf2573
commit 2f4e505aac
9 changed files with 114 additions and 15 deletions
+1
View File
@@ -10,6 +10,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
- socks5 client/websocket client: add `--force-register-gateway` flag, useful when rerunning init ([#1353])
- nym-connect: initial proof-of-concept of a UI around the socks5 client was added
- nym-connect: add ability to select network requester and gateway ([#1427]).
- nym-connect: add ability to export gateway keys as JSON.
- all: added network compilation target to `--help` (or `--version`) commands ([#1256]).
- explorer-api: learned how to sum the delegations by owner in a new endpoint.
- explorer-api: add apy values to `mix_nodes` endpoint
+8 -5
View File
@@ -287,12 +287,15 @@ impl NymClient {
pub async fn run_and_listen(&mut self, mut receiver: Socks5ControlMessageReceiver) {
self.start().await;
tokio::select! {
message = receiver.next() => match message {
Some(Socks5ControlMessage::Stop) => {
log::info!("Received: {:?}", message);
log::info!("Shutting down");
message = receiver.next() => {
log::debug!("Received message: {:?}", message);
match message {
Some(Socks5ControlMessage::Stop) => {
log::info!("Shutting down");
log::info!("Graceful shutdown of tasks not yet implemented, you might see (harmless) panics until then");
}
None => log::debug!("None"),
}
None => log::info!("none"),
}
}
}
+5 -6
View File
@@ -1,7 +1,6 @@
use std::path::PathBuf;
use client_core::config::GatewayEndpoint;
use log::info;
use std::sync::Arc;
use tap::TapFallible;
use tokio::sync::RwLock;
@@ -15,7 +14,7 @@ use crate::{
state::State,
};
pub static SOCKS5_CONFIG_ID: &str = "nym-connect";
static SOCKS5_CONFIG_ID: &str = "nym-connect";
const DEFAULT_ETH_ENDPOINT: &str = "https://rinkeby.infura.io/v3/00000000000000000000000000000000";
const DEFAULT_ETH_PRIVATE_KEY: &str =
@@ -73,7 +72,7 @@ impl Config {
}
pub async fn init(service_provider: &str, chosen_gateway_id: &str) -> Result<()> {
info!("Initialising...");
log::info!("Initialising...");
let service_provider = service_provider.to_owned();
let chosen_gateway_id = chosen_gateway_id.to_owned();
@@ -91,7 +90,7 @@ impl Config {
.join()
.map_err(|_| BackendError::InitializationPanic)??;
info!("Configuration saved 🚀");
log::info!("Configuration saved 🚀");
Ok(())
}
@@ -101,7 +100,7 @@ impl Config {
}
pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: String) -> Result<()> {
log::info!("Initialising client...");
log::trace!("Initialising client...");
// Append the gateway id to the name id that we store the config under
let id = socks5_config_id_appended_with(&chosen_gateway_id)?;
@@ -166,7 +165,7 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str
"Service provider port: {}",
config.get_socks5().get_listening_port()
);
info!("Client configuration completed.");
log::info!("Client configuration completed.");
client_core::init::show_address(config.get_base());
Ok(())
+7
View File
@@ -24,6 +24,11 @@ pub enum BackendError {
#[from]
source: tauri::Error,
},
#[error("{source}")]
SerdeJsonError {
#[from]
source: serde_json::Error,
},
#[error("State error")]
StateError,
@@ -45,6 +50,8 @@ pub enum BackendError {
CouldNotInitWithoutGateway,
#[error("Could initialize without service provider set")]
CouldNotInitWithoutServiceProvider,
#[error("Could not get file name")]
CouldNotGetFilename,
}
impl Serialize for BackendError {
+2 -1
View File
@@ -43,8 +43,9 @@ fn main() {
crate::operations::connection::connect::set_service_provider,
crate::operations::connection::connect::start_connecting,
crate::operations::connection::disconnect::start_disconnecting,
crate::operations::window::hide_window,
crate::operations::directory::get_services,
crate::operations::export::export_keys,
crate::operations::window::hide_window,
])
.menu(Menu::new().add_default_app_submenu_if_macos())
.system_tray(create_tray_menu())
@@ -0,0 +1,73 @@
use std::{ffi::OsStr, fs, sync::Arc};
use tokio::sync::RwLock;
use crate::{
error::{BackendError, Result},
state::State,
};
/// Export the gateway keys as a JSON string blob
#[tauri::command]
pub async fn export_keys(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<String> {
let config = {
let state = state.read().await;
state.load_socks5_config()?
};
// Get key paths
let ack_key_file = config.get_base().get_ack_key_file();
let gateway_shared_key_file = config.get_base().get_gateway_shared_key_file();
let pub_id_key_file = config.get_base().get_public_identity_key_file();
let priv_id_key_file = config.get_base().get_private_identity_key_file();
let pub_enc_key_file = config.get_base().get_public_encryption_key_file();
let priv_enc_key_file = config.get_base().get_private_encryption_key_file();
// Read file contents
let ack_key = fs::read_to_string(ack_key_file.clone())?;
let gateway_shared_key = fs::read_to_string(gateway_shared_key_file.clone())?;
let pub_id_key = fs::read_to_string(pub_id_key_file.clone())?;
let priv_id_key = fs::read_to_string(priv_id_key_file.clone())?;
let pub_enc_key = fs::read_to_string(pub_enc_key_file.clone())?;
let priv_enc_key = fs::read_to_string(priv_enc_key_file.clone())?;
let ack_key_file = ack_key_file
.file_name()
.map(OsStr::to_string_lossy)
.ok_or(BackendError::CouldNotGetFilename)?;
let gateway_shared_key_file = gateway_shared_key_file
.file_name()
.map(OsStr::to_string_lossy)
.ok_or(BackendError::CouldNotGetFilename)?;
let pub_id_key_file = pub_id_key_file
.file_name()
.map(OsStr::to_string_lossy)
.ok_or(BackendError::CouldNotGetFilename)?;
let priv_id_key_file = priv_id_key_file
.file_name()
.map(OsStr::to_string_lossy)
.ok_or(BackendError::CouldNotGetFilename)?;
let pub_enc_key_file = pub_enc_key_file
.file_name()
.map(OsStr::to_string_lossy)
.ok_or(BackendError::CouldNotGetFilename)?;
let priv_enc_key_file = priv_enc_key_file
.file_name()
.map(OsStr::to_string_lossy)
.ok_or(BackendError::CouldNotGetFilename)?;
// Format and return as json
let json = serde_json::json!({
ack_key_file: ack_key,
gateway_shared_key_file: gateway_shared_key,
pub_id_key_file: pub_id_key,
priv_id_key_file: priv_id_key,
pub_enc_key_file: pub_enc_key,
priv_enc_key_file: priv_enc_key,
});
Ok(serde_json::to_string_pretty(&json)?)
}
@@ -1,3 +1,4 @@
pub mod connection;
pub mod directory;
pub mod export;
pub mod window;
+11 -1
View File
@@ -1,10 +1,13 @@
use std::time::Duration;
use ::config::NymConfig;
use futures::SinkExt;
use tap::TapFallible;
use tauri::Manager;
use nym_socks5::client::{Socks5ControlMessage, Socks5ControlMessageSender};
use nym_socks5::client::{
config::Config as Socks5Config, Socks5ControlMessage, Socks5ControlMessageSender,
};
use crate::{
config::{self, socks5_config_id_appended_with},
@@ -81,6 +84,13 @@ impl State {
.and_then(|gateway_id| socks5_config_id_appended_with(gateway_id))
}
pub fn load_socks5_config(&self) -> Result<Socks5Config> {
let id = self.get_config_id()?;
let config = Socks5Config::load_from_file(Some(&id))
.tap_err(|_| log::warn!("Failed to load configuration file"))?;
Ok(config)
}
/// Start connecting by first creating a config file, followed by starting a thread running the
/// SOCKS5 client.
pub async fn start_connecting(
+6 -2
View File
@@ -7,23 +7,25 @@ use tokio::sync::RwLock;
use config::NymConfig;
#[cfg(not(feature = "coconut"))]
use nym_socks5::client::NymClient as Socks5NymClient;
use nym_socks5::client::Socks5ControlMessageSender;
use nym_socks5::client::{config::Config as Socks5Config, Socks5ControlMessageSender};
use crate::{error::Result, state::State};
pub type StatusReceiver = futures::channel::oneshot::Receiver<Socks5StatusMessage>;
/// Status messages sent by the SOCKS5 client task to the main tauri task.
#[derive(Debug)]
pub enum Socks5StatusMessage {
/// The SOCKS5 task successfully stopped
Stopped,
}
/// The main SOCKS5 client task. It loads the configuration from file determined by the `id`.
pub fn start_nym_socks5_client(
id: &str,
) -> Result<(Socks5ControlMessageSender, StatusReceiver, GatewayEndpoint)> {
log::info!("Loading config from file: {id}");
let config = nym_socks5::client::config::Config::load_from_file(Some(id))
let config = Socks5Config::load_from_file(Some(id))
.tap_err(|_| log::warn!("Failed to load configuration file"))?;
let used_gateway = config.get_base().get_gateway_endpoint().clone();
@@ -54,6 +56,8 @@ pub fn start_nym_socks5_client(
Ok((socks5_ctrl_tx, socks5_status_rx, used_gateway))
}
/// The disconnect listener listens to the channel setup between the socks5 proxy task and the main
/// tauri task. Primarily it listens for shutdown messages, and updates the state accordingly.
pub fn start_disconnect_listener(
state: Arc<RwLock<State>>,
window: tauri::Window<tauri::Wry>,