From 3ccdafbda235730ec95d6f2992808beb2eb51aa9 Mon Sep 17 00:00:00 2001 From: jp1ac4 <121959000+jp1ac4@users.noreply.github.com> Date: Thu, 21 Dec 2023 13:55:50 +0000 Subject: [PATCH 1/3] gui: support user/password RPC authentication This change updates the GUI to support the latest lianad config file with the user/password option for bitcoind RPC authentication. The settings have been updated to set either cookie file path or user and password. The installer still only supports the cookie file and has only been updated with the changes required to compile. When starting, the internal bitcoind now looks for the cookie file in the usual location rather than relying on the config file. --- gui/Cargo.lock | 2 +- gui/src/app/state/settings/bitcoind.rs | 74 +++++++++++++++++++---- gui/src/app/view/message.rs | 3 +- gui/src/app/view/settings.rs | 83 +++++++++++++++++++++----- gui/src/bitcoind.rs | 36 +++++++++-- gui/src/installer/step/bitcoind.rs | 4 +- 6 files changed, 164 insertions(+), 38 deletions(-) diff --git a/gui/Cargo.lock b/gui/Cargo.lock index c353e4cb..4b889c27 100644 --- a/gui/Cargo.lock +++ b/gui/Cargo.lock @@ -2431,7 +2431,7 @@ dependencies = [ [[package]] name = "liana" version = "4.0.0" -source = "git+https://github.com/wizardsardine/liana?branch=master#dee069e72343a67607f4429125e4c80dc0d73055" +source = "git+https://github.com/wizardsardine/liana?branch=master#b8f8d1b944120879986a71255bab19e5b342ecc8" dependencies = [ "backtrace", "bdk_coin_select", diff --git a/gui/src/app/state/settings/bitcoind.rs b/gui/src/app/state/settings/bitcoind.rs index 02b65767..37054101 100644 --- a/gui/src/app/state/settings/bitcoind.rs +++ b/gui/src/app/state/settings/bitcoind.rs @@ -8,12 +8,13 @@ use chrono::prelude::*; use iced::Command; use tracing::info; -use liana::config::{BitcoinConfig, BitcoindConfig, Config}; +use liana::config::{BitcoinConfig, BitcoindConfig, BitcoindRpcAuth, Config}; use liana_ui::{component::form, widget::Element}; use crate::{ app::{cache::Cache, error::Error, message::Message, state::settings::Setting, view, State}, + bitcoind::{RpcAuthType, RpcAuthValues}, daemon::Daemon, }; @@ -140,7 +141,8 @@ pub struct BitcoindSettings { bitcoin_config: BitcoinConfig, edit: bool, processing: bool, - cookie_path: form::Value, + rpc_auth_vals: RpcAuthValues, + selected_auth_type: RpcAuthType, addr: form::Value, daemon_is_external: bool, bitcoind_is_internal: bool, @@ -159,7 +161,33 @@ impl BitcoindSettings { daemon_is_external: bool, bitcoind_is_internal: bool, ) -> BitcoindSettings { - let path = bitcoind_config.cookie_path.to_str().unwrap().to_string(); + let (rpc_auth_vals, selected_auth_type) = match &bitcoind_config.rpc_auth { + BitcoindRpcAuth::CookieFile(path) => ( + RpcAuthValues { + cookie_path: form::Value { + valid: true, + value: path.to_str().unwrap().to_string(), + }, + user: form::Value::default(), + password: form::Value::default(), + }, + RpcAuthType::CookieFile, + ), + BitcoindRpcAuth::UserPass(user, password) => ( + RpcAuthValues { + cookie_path: form::Value::default(), + user: form::Value { + valid: true, + value: user.clone(), + }, + password: form::Value { + valid: true, + value: password.clone(), + }, + }, + RpcAuthType::UserPass, + ), + }; let addr = bitcoind_config.addr.to_string(); BitcoindSettings { daemon_is_external, @@ -168,10 +196,8 @@ impl BitcoindSettings { bitcoin_config, edit: false, processing: false, - cookie_path: form::Value { - valid: true, - value: path, - }, + rpc_auth_vals, + selected_auth_type, addr: form::Value { valid: true, value: addr, @@ -209,21 +235,41 @@ impl Setting for BitcoindSettings { if !self.processing { match field { "socket_address" => self.addr.value = value, - "cookie_file_path" => self.cookie_path.value = value, + "cookie_file_path" => self.rpc_auth_vals.cookie_path.value = value, + "user" => self.rpc_auth_vals.user.value = value, + "password" => self.rpc_auth_vals.password.value = value, _ => {} } } } + view::SettingsEditMessage::BitcoindRpcAuthTypeSelected(auth_type) => { + if !self.processing { + self.selected_auth_type = auth_type; + } + } view::SettingsEditMessage::Confirm => { let new_addr = SocketAddr::from_str(&self.addr.value); self.addr.valid = new_addr.is_ok(); - let new_path = PathBuf::from_str(&self.cookie_path.value); - self.cookie_path.valid = new_path.is_ok(); + let rpc_auth = match self.selected_auth_type { + RpcAuthType::CookieFile => { + let new_path = PathBuf::from_str(&self.rpc_auth_vals.cookie_path.value); + if let Ok(path) = new_path { + self.rpc_auth_vals.cookie_path.valid = true; + Some(BitcoindRpcAuth::CookieFile(path)) + } else { + None + } + } + RpcAuthType::UserPass => Some(BitcoindRpcAuth::UserPass( + self.rpc_auth_vals.user.value.clone(), + self.rpc_auth_vals.password.value.clone(), + )), + }; - if self.addr.valid & self.cookie_path.valid { + if let (true, Some(rpc_auth)) = (self.addr.valid, rpc_auth) { let mut daemon_config = daemon.config().cloned().unwrap(); daemon_config.bitcoind_config = Some(liana::config::BitcoindConfig { - cookie_path: new_path.unwrap(), + rpc_auth, addr: new_addr.unwrap(), }); self.processing = true; @@ -242,7 +288,8 @@ impl Setting for BitcoindSettings { self.bitcoin_config.network, cache.blockheight, &self.addr, - &self.cookie_path, + &self.rpc_auth_vals, + &self.selected_auth_type, self.processing, ) } else { @@ -342,6 +389,7 @@ impl Setting for RescanSetting { Message::StartRescan, ); } + _ => {} }; Command::none() } diff --git a/gui/src/app/view/message.rs b/gui/src/app/view/message.rs index 919441d2..44cd6043 100644 --- a/gui/src/app/view/message.rs +++ b/gui/src/app/view/message.rs @@ -1,4 +1,4 @@ -use crate::app::menu::Menu; +use crate::{app::menu::Menu, bitcoind::RpcAuthType}; use liana::miniscript::bitcoin::bip32::Fingerprint; #[derive(Debug, Clone)] @@ -75,6 +75,7 @@ pub enum SettingsMessage { pub enum SettingsEditMessage { Select, FieldEdited(&'static str, String), + BitcoindRpcAuthTypeSelected(RpcAuthType), Cancel, Confirm, } diff --git a/gui/src/app/view/settings.rs b/gui/src/app/view/settings.rs index 2b896b15..4618ad4b 100644 --- a/gui/src/app/view/settings.rs +++ b/gui/src/app/view/settings.rs @@ -3,11 +3,14 @@ use std::str::FromStr; use iced::{ alignment, - widget::{scrollable, Space}, + widget::{radio, scrollable, Space}, Alignment, Length, }; -use liana::miniscript::bitcoin::{bip32::Fingerprint, Network}; +use liana::{ + config::BitcoindRpcAuth, + miniscript::bitcoin::{bip32::Fingerprint, Network}, +}; use super::{dashboard, message::*}; @@ -26,6 +29,7 @@ use crate::{ menu::Menu, view::{hw, warning::warn}, }, + bitcoind::{RpcAuthType, RpcAuthValues}, hw::HardwareWallet, }; @@ -208,7 +212,8 @@ pub fn bitcoind_edit<'a>( network: Network, blockheight: i32, addr: &form::Value, - cookie_path: &form::Value, + rpc_auth_vals: &RpcAuthValues, + selected_auth_type: &RpcAuthType, processing: bool, ) -> Element<'a, SettingsEditMessage> { let mut col = Column::new().spacing(20); @@ -244,18 +249,60 @@ pub fn bitcoind_edit<'a>( col = col .push( - Column::new() - .push(text("Cookie file path:").bold().small()) + [RpcAuthType::CookieFile, RpcAuthType::UserPass] + .iter() + .fold( + Row::new() + .push(text("RPC authentication:").small().bold()) + .spacing(10), + |row, auth_type| { + row.push(radio( + format!("{}", auth_type), + *auth_type, + Some(*selected_auth_type), + SettingsEditMessage::BitcoindRpcAuthTypeSelected, + )) + .spacing(30) + .align_items(Alignment::Center) + }, + ), + ) + .push(match selected_auth_type { + RpcAuthType::CookieFile => Column::new() .push( - form::Form::new_trimmed("Cookie file path", cookie_path, |value| { - SettingsEditMessage::FieldEdited("cookie_file_path", value) - }) + form::Form::new_trimmed( + "Cookie file path", + &rpc_auth_vals.cookie_path, + |value| SettingsEditMessage::FieldEdited("cookie_file_path", value), + ) .warning("Please enter a valid filesystem path") .size(20) .padding(5), ) .spacing(5), - ) + RpcAuthType::UserPass => Column::new() + .push( + Row::new() + .push( + form::Form::new_trimmed("User", &rpc_auth_vals.user, |value| { + SettingsEditMessage::FieldEdited("user", value) + }) + .warning("Please enter a valid user") + .size(20) + .padding(5), + ) + .push( + form::Form::new_trimmed("Password", &rpc_auth_vals.password, |value| { + SettingsEditMessage::FieldEdited("password", value) + }) + .warning("Please enter a valid password") + .size(20) + .padding(5), + ) + .spacing(10), + ) + .spacing(5), + }) .push( Column::new() .push(text("Socket address:").bold().small()) @@ -345,13 +392,17 @@ pub fn bitcoind<'a>( .push(separation().width(Length::Fill)); } - let rows = vec![ - ( - "Cookie file path:", - config.cookie_path.to_str().unwrap().to_string(), - ), - ("Socket address:", config.addr.to_string()), - ]; + let mut rows = vec![]; + match &config.rpc_auth { + BitcoindRpcAuth::CookieFile(path) => { + rows.push(("Cookie file path:", path.to_str().unwrap().to_string())); + } + BitcoindRpcAuth::UserPass(user, password) => { + rows.push(("User:", user.clone())); + rows.push(("Password:", password.clone())); + } + } + rows.push(("Socket address:", config.addr.to_string())); let mut col_fields = Column::new(); for (k, v) in rows { diff --git a/gui/src/bitcoind.rs b/gui/src/bitcoind.rs index f6a3f0d5..a04719d3 100644 --- a/gui/src/bitcoind.rs +++ b/gui/src/bitcoind.rs @@ -1,7 +1,9 @@ use liana::{ - config::BitcoindConfig, + config::{BitcoindConfig, BitcoindRpcAuth}, miniscript::bitcoin::{self, Network}, }; +use liana_ui::component::form; +use std::fmt; use std::path::{Path, PathBuf}; use std::sync::Arc; use std::thread; @@ -222,6 +224,7 @@ impl Bitcoind { // We've started bitcoind in the background, however it may fail to start for whatever // reason. And we need its JSONRPC interface to be available to continue. Thus wait for it // to have created the cookie file, regularly checking it did not fail to start. + let cookie_path = internal_bitcoind_cookie_path(&bitcoind_datadir, network); loop { match process.try_wait() { Ok(None) => {} @@ -229,11 +232,11 @@ impl Bitcoind { Ok(Some(status)) => { log::error!("Bitcoind exited with status '{}'", status); return Err(StartInternalBitcoindError::CookieFileNotFound( - config.cookie_path.to_string_lossy().into_owned(), + cookie_path.to_string_lossy().into_owned(), )); } } - if config.cookie_path.exists() { + if cookie_path.exists() { log::info!("Bitcoind seems to have successfully started."); break; } @@ -241,9 +244,10 @@ impl Bitcoind { thread::sleep(time::Duration::from_millis(500)); } - config.cookie_path = config.cookie_path.canonicalize().map_err(|e| { + config.rpc_auth = BitcoindRpcAuth::CookieFile(cookie_path.canonicalize().map_err(|e| { StartInternalBitcoindError::CouldNotCanonicalizeCookiePath(e.to_string()) - })?; + })?); + liana::BitcoinD::new(&config, "internal_bitcoind_start".to_string()) .map_err(|e| StartInternalBitcoindError::BitcoinDError(e.to_string()))?; @@ -273,3 +277,25 @@ pub fn stop_bitcoind(config: &BitcoindConfig) -> bool { } } } + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum RpcAuthType { + CookieFile, + UserPass, +} + +impl fmt::Display for RpcAuthType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + RpcAuthType::CookieFile => write!(f, "Cookie file path"), + RpcAuthType::UserPass => write!(f, "User and password"), + } + } +} + +#[derive(Debug, Clone, Default)] +pub struct RpcAuthValues { + pub cookie_path: form::Value, + pub user: form::Value, + pub password: form::Value, +} diff --git a/gui/src/installer/step/bitcoind.rs b/gui/src/installer/step/bitcoind.rs index 544cb415..eb3461dc 100644 --- a/gui/src/installer/step/bitcoind.rs +++ b/gui/src/installer/step/bitcoind.rs @@ -554,7 +554,7 @@ impl Step for DefineBitcoind { } (Ok(path), Ok(addr)) => { ctx.bitcoind_config = Some(BitcoindConfig { - cookie_path: path, + rpc_auth: liana::config::BitcoindRpcAuth::CookieFile(path), addr, }); true @@ -803,7 +803,7 @@ impl Step for InternalBitcoindStep { match Bitcoind::start( &self.network, BitcoindConfig { - cookie_path, + rpc_auth: liana::config::BitcoindRpcAuth::CookieFile(cookie_path), addr: internal_bitcoind_address(rpc_port), }, &self.liana_datadir, From 38198cc79f29fd13b52f963ce8fe7da2567b3bb4 Mon Sep 17 00:00:00 2001 From: jp1ac4 <121959000+jp1ac4@users.noreply.github.com> Date: Fri, 22 Dec 2023 17:38:26 +0000 Subject: [PATCH 2/3] installer: support user/password RPC authentication If using a self-managed node, this adds the option to authenticate with the RPC server using user and password. --- gui/src/bitcoind.rs | 19 +++++ gui/src/installer/message.rs | 10 ++- gui/src/installer/step/bitcoind.rs | 113 +++++++++++++++++++---------- gui/src/installer/view.rs | 82 +++++++++++++++++---- 4 files changed, 169 insertions(+), 55 deletions(-) diff --git a/gui/src/bitcoind.rs b/gui/src/bitcoind.rs index a04719d3..69aaa5dc 100644 --- a/gui/src/bitcoind.rs +++ b/gui/src/bitcoind.rs @@ -299,3 +299,22 @@ pub struct RpcAuthValues { pub user: form::Value, pub password: form::Value, } + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum ConfigField { + Address, + CookieFilePath, + User, + Password, +} + +impl fmt::Display for ConfigField { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ConfigField::Address => write!(f, "Socket address"), + ConfigField::CookieFilePath => write!(f, "Cookie file path"), + ConfigField::User => write!(f, "User"), + ConfigField::Password => write!(f, "Password"), + } + } +} diff --git a/gui/src/installer/message.rs b/gui/src/installer/message.rs index 66cb21e7..d6e8afad 100644 --- a/gui/src/installer/message.rs +++ b/gui/src/installer/message.rs @@ -5,7 +5,11 @@ use liana::miniscript::{ use std::path::PathBuf; use super::Error; -use crate::{bitcoind::Bitcoind, download::Progress, hw::HardwareWalletMessage}; +use crate::{ + bitcoind::{Bitcoind, ConfigField, RpcAuthType}, + download::Progress, + hw::HardwareWalletMessage, +}; use async_hwi::DeviceKind; #[derive(Debug, Clone)] @@ -39,8 +43,8 @@ pub enum Message { #[derive(Debug, Clone)] pub enum DefineBitcoind { - CookiePathEdited(String), - AddressEdited(String), + ConfigFieldEdited(ConfigField, String), + RpcAuthTypeSelected(RpcAuthType), PingBitcoindResult(Result<(), Error>), PingBitcoind, } diff --git a/gui/src/installer/step/bitcoind.rs b/gui/src/installer/step/bitcoind.rs index eb3461dc..6572d36d 100644 --- a/gui/src/installer/step/bitcoind.rs +++ b/gui/src/installer/step/bitcoind.rs @@ -9,7 +9,10 @@ use bitcoin_hashes::{sha256, Hash}; #[cfg(any(target_os = "macos", target_os = "linux"))] use flate2::read::GzDecoder; use iced::{Command, Subscription}; -use liana::{config::BitcoindConfig, miniscript::bitcoin::Network}; +use liana::{ + config::{BitcoindConfig, BitcoindRpcAuth}, + miniscript::bitcoin::Network, +}; #[cfg(any(target_os = "macos", target_os = "linux"))] use tar::Archive; use tracing::info; @@ -21,7 +24,7 @@ use liana_ui::{component::form, widget::*}; use crate::{ bitcoind::{ self, bitcoind_network_dir, internal_bitcoind_datadir, internal_bitcoind_directory, - Bitcoind, StartInternalBitcoindError, VERSION, + Bitcoind, ConfigField, RpcAuthType, RpcAuthValues, StartInternalBitcoindError, VERSION, }, download, hw::HardwareWallets, @@ -465,7 +468,8 @@ impl Step for SelectBitcoindTypeStep { } pub struct DefineBitcoind { - cookie_path: form::Value, + rpc_auth_vals: RpcAuthValues, + selected_auth_type: RpcAuthType, address: form::Value, is_running: Option>, } @@ -473,7 +477,8 @@ pub struct DefineBitcoind { impl DefineBitcoind { pub fn new() -> Self { Self { - cookie_path: form::Value::default(), + rpc_auth_vals: RpcAuthValues::default(), + selected_auth_type: RpcAuthType::CookieFile, address: form::Value::default(), is_running: None, } @@ -481,16 +486,28 @@ impl DefineBitcoind { pub fn ping(&self) -> Command { let address = self.address.value.to_owned(); - let cookie_path = self.cookie_path.value.to_owned(); + let selected_auth_type = self.selected_auth_type; + let rpc_auth_vals = self.rpc_auth_vals.clone(); Command::perform( async move { - let cookie = std::fs::read_to_string(&cookie_path) - .map_err(|e| Error::Bitcoind(format!("Failed to read cookie file: {}", e)))?; + let builder = match selected_auth_type { + RpcAuthType::CookieFile => { + let cookie_path = rpc_auth_vals.cookie_path.value; + let cookie = std::fs::read_to_string(&cookie_path).map_err(|e| { + Error::Bitcoind(format!("Failed to read cookie file: {}", e)) + })?; + SimpleHttpTransport::builder().cookie_auth(cookie) + } + RpcAuthType::UserPass => { + let user = rpc_auth_vals.user.value; + let password = rpc_auth_vals.password.value; + SimpleHttpTransport::builder().auth(user, Some(password)) + } + }; let client = Client::with_transport( - SimpleHttpTransport::builder() + builder .url(&address)? .timeout(std::time::Duration::from_secs(3)) - .cookie_auth(cookie) .build(), ); client.send_request(client.build_request("echo", &[]))?; @@ -503,8 +520,8 @@ impl DefineBitcoind { impl Step for DefineBitcoind { fn load_context(&mut self, ctx: &Context) { - if self.cookie_path.value.is_empty() { - self.cookie_path.value = + if self.rpc_auth_vals.cookie_path.value.is_empty() { + self.rpc_auth_vals.cookie_path.value = bitcoind_default_cookie_path(&ctx.bitcoin_config.network).unwrap_or_default() } if self.address.value.is_empty() { @@ -519,15 +536,31 @@ impl Step for DefineBitcoind { return self.ping(); } message::DefineBitcoind::PingBitcoindResult(res) => self.is_running = Some(res), - message::DefineBitcoind::AddressEdited(address) => { + message::DefineBitcoind::ConfigFieldEdited(field, value) => match field { + ConfigField::Address => { + self.is_running = None; + self.address.value = value; + self.address.valid = true; + } + ConfigField::CookieFilePath => { + self.is_running = None; + self.rpc_auth_vals.cookie_path.value = value; + self.rpc_auth_vals.cookie_path.valid = true; + } + ConfigField::User => { + self.is_running = None; + self.rpc_auth_vals.user.value = value; + self.rpc_auth_vals.user.valid = true; + } + ConfigField::Password => { + self.is_running = None; + self.rpc_auth_vals.password.value = value; + self.rpc_auth_vals.password.valid = true; + } + }, + message::DefineBitcoind::RpcAuthTypeSelected(auth_type) => { self.is_running = None; - self.address.value = address; - self.address.valid = true; - } - message::DefineBitcoind::CookiePathEdited(path) => { - self.is_running = None; - self.cookie_path.value = path; - self.address.valid = true; + self.selected_auth_type = auth_type; } }; }; @@ -535,28 +568,29 @@ impl Step for DefineBitcoind { } fn apply(&mut self, ctx: &mut Context) -> bool { - match ( - PathBuf::from_str(&self.cookie_path.value), - std::net::SocketAddr::from_str(&self.address.value), - ) { - (Err(_), Ok(_)) => { - self.cookie_path.valid = false; - false + let addr = std::net::SocketAddr::from_str(&self.address.value); + let rpc_auth = match self.selected_auth_type { + RpcAuthType::CookieFile => { + if let Ok(path) = PathBuf::from_str(&self.rpc_auth_vals.cookie_path.value) { + Some(BitcoindRpcAuth::CookieFile(path)) + } else { + self.rpc_auth_vals.cookie_path.valid = false; + None + } } - (Ok(_), Err(_)) => { + RpcAuthType::UserPass => Some(BitcoindRpcAuth::UserPass( + self.rpc_auth_vals.user.value.clone(), + self.rpc_auth_vals.password.value.clone(), + )), + }; + match (rpc_auth, addr) { + (None, Ok(_)) => false, + (_, Err(_)) => { self.address.valid = false; false } - (Err(_), Err(_)) => { - self.cookie_path.valid = false; - self.address.valid = false; - false - } - (Ok(path), Ok(addr)) => { - ctx.bitcoind_config = Some(BitcoindConfig { - rpc_auth: liana::config::BitcoindRpcAuth::CookieFile(path), - addr, - }); + (Some(rpc_auth), Ok(addr)) => { + ctx.bitcoind_config = Some(BitcoindConfig { rpc_auth, addr }); true } } @@ -566,7 +600,8 @@ impl Step for DefineBitcoind { view::define_bitcoin( progress, &self.address, - &self.cookie_path, + &self.rpc_auth_vals, + &self.selected_auth_type, self.is_running.as_ref(), ) } @@ -803,7 +838,7 @@ impl Step for InternalBitcoindStep { match Bitcoind::start( &self.network, BitcoindConfig { - rpc_auth: liana::config::BitcoindRpcAuth::CookieFile(cookie_path), + rpc_auth: BitcoindRpcAuth::CookieFile(cookie_path), addr: internal_bitcoind_address(rpc_port), }, &self.liana_datadir, diff --git a/gui/src/installer/view.rs b/gui/src/installer/view.rs index 02e78d8c..6ed49ad7 100644 --- a/gui/src/installer/view.rs +++ b/gui/src/installer/view.rs @@ -1,5 +1,6 @@ use iced::widget::{ - checkbox, container, pick_list, scrollable, scrollable::Properties, slider, Space, TextInput, + checkbox, container, pick_list, radio, scrollable, scrollable::Properties, slider, Space, + TextInput, }; use iced::{alignment, widget::progress_bar, Alignment, Length}; @@ -21,7 +22,7 @@ use liana_ui::{ }; use crate::{ - bitcoind::StartInternalBitcoindError, + bitcoind::{ConfigField, RpcAuthType, RpcAuthValues, StartInternalBitcoindError}, hw::HardwareWallet, installer::{ message::{self, Message}, @@ -787,14 +788,18 @@ pub fn help_backup<'a>() -> Element<'a, Message> { pub fn define_bitcoin<'a>( progress: (usize, usize), address: &form::Value, - cookie_path: &form::Value, + rpc_auth_vals: &RpcAuthValues, + selected_auth_type: &RpcAuthType, is_running: Option<&Result<(), Error>>, ) -> Element<'a, Message> { let col_address = Column::new() .push(text("Address:").bold()) .push( form::Form::new_trimmed("Address", address, |msg| { - Message::DefineBitcoind(message::DefineBitcoind::AddressEdited(msg)) + Message::DefineBitcoind(message::DefineBitcoind::ConfigFieldEdited( + ConfigField::Address, + msg, + )) }) .warning("Please enter correct address") .size(20) @@ -802,16 +807,67 @@ pub fn define_bitcoin<'a>( ) .spacing(10); - let col_cookie = Column::new() - .push(text("Cookie path:").bold()) + let col_auth = Column::new() .push( - form::Form::new_trimmed("Cookie path", cookie_path, |msg| { - Message::DefineBitcoind(message::DefineBitcoind::CookiePathEdited(msg)) - }) - .warning("Please enter correct path") - .size(20) - .padding(10), + [RpcAuthType::CookieFile, RpcAuthType::UserPass] + .iter() + .fold( + Row::new() + .push(text("RPC authentication:").small().bold()) + .spacing(10), + |row, auth_type| { + row.push(radio( + format!("{}", auth_type), + *auth_type, + Some(*selected_auth_type), + |new_selection| { + Message::DefineBitcoind( + message::DefineBitcoind::RpcAuthTypeSelected(new_selection), + ) + }, + )) + .spacing(30) + .align_items(Alignment::Center) + }, + ), ) + .push(match selected_auth_type { + RpcAuthType::CookieFile => Row::new().push( + form::Form::new_trimmed("Cookie path", &rpc_auth_vals.cookie_path, |msg| { + Message::DefineBitcoind(message::DefineBitcoind::ConfigFieldEdited( + ConfigField::CookieFilePath, + msg, + )) + }) + .warning("Please enter correct path") + .size(20) + .padding(10), + ), + RpcAuthType::UserPass => Row::new() + .push( + form::Form::new_trimmed("User", &rpc_auth_vals.user, |msg| { + Message::DefineBitcoind(message::DefineBitcoind::ConfigFieldEdited( + ConfigField::User, + msg, + )) + }) + .warning("Please enter correct user") + .size(20) + .padding(10), + ) + .push( + form::Form::new_trimmed("Password", &rpc_auth_vals.password, |msg| { + Message::DefineBitcoind(message::DefineBitcoind::ConfigFieldEdited( + ConfigField::Password, + msg, + )) + }) + .warning("Please enter correct password") + .size(20) + .padding(10), + ) + .spacing(10), + }) .spacing(10); layout( @@ -819,7 +875,7 @@ pub fn define_bitcoin<'a>( "Set up connection to the Bitcoin full node", Column::new() .push(col_address) - .push(col_cookie) + .push(col_auth) .push_maybe(if is_running.is_some() { is_running.map(|res| { if res.is_ok() { From 838550b917d96a6a6d11f5d0103c53706acd9a8c Mon Sep 17 00:00:00 2001 From: jp1ac4 <121959000+jp1ac4@users.noreply.github.com> Date: Thu, 28 Dec 2023 17:21:23 +0000 Subject: [PATCH 3/3] gui: change radio border color --- gui/ui/src/theme.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gui/ui/src/theme.rs b/gui/ui/src/theme.rs index 20fb3380..777ba1a0 100644 --- a/gui/ui/src/theme.rs +++ b/gui/ui/src/theme.rs @@ -345,7 +345,7 @@ impl radio::StyleSheet for Theme { background: iced::Color::TRANSPARENT.into(), dot_color: color::GREEN, border_width: 1.0, - border_color: color::GREEN, + border_color: color::GREY_7, text_color: None, } } @@ -354,6 +354,7 @@ impl radio::StyleSheet for Theme { let active = self.active(style, is_selected); radio::Appearance { dot_color: color::GREEN, + border_color: color::GREEN, background: iced::Color::TRANSPARENT.into(), ..active }