diff --git a/CHANGELOG.md b/CHANGELOG.md index 24ef8c5..3a1a948 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Procedure when bumping the version number: - Config file - `ephemeral` config option - `data_dir` config option +- `euph.rooms..password` config option ## v0.3.0 - 2022-08-22 diff --git a/src/config.rs b/src/config.rs index 2513838..f984e14 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::fs; use std::path::{Path, PathBuf}; @@ -5,11 +6,22 @@ use serde::Deserialize; use crate::macros::ok_or_return; +#[derive(Debug, Clone, Default, Deserialize)] +pub struct EuphRoom { + pub password: Option, +} + +#[derive(Debug, Default, Deserialize)] +pub struct Euph { + pub rooms: HashMap, +} + #[derive(Debug, Default, Deserialize)] pub struct Config { pub data_dir: Option, #[serde(default)] pub ephemeral: bool, + pub euph: Euph, } impl Config { @@ -23,4 +35,8 @@ impl Config { } } } + + pub fn euph_room(&self, name: &str) -> EuphRoom { + self.euph.rooms.get(name).cloned().unwrap_or_default() + } } diff --git a/src/euph/room.rs b/src/euph/room.rs index 324196f..cef9321 100644 --- a/src/euph/room.rs +++ b/src/euph/room.rs @@ -58,6 +58,7 @@ enum Event { #[derive(Debug)] struct State { name: String, + password: Option, vault: EuphVault, conn_tx: Option, @@ -231,7 +232,14 @@ impl State { async fn on_packet(&mut self, packet: &ParsedPacket) -> anyhow::Result<()> { let data = ok_or_return!(&packet.content, Ok(())); match data { - Data::BounceEvent(_) => {} + Data::BounceEvent(_) => { + if let Some(password) = &self.password { + // Try to authenticate with the configured password, but no + // promises if it doesn't work. In particular, we only ever + // try this password once. + self.on_auth(password.clone()); + } + } Data::DisconnectEvent(d) => { warn!("e&{}: disconnected for reason {:?}", self.name, d.reason); } @@ -411,7 +419,10 @@ pub struct Room { } impl Room { - pub fn new(vault: EuphVault) -> (Self, mpsc::UnboundedReceiver) { + pub fn new( + vault: EuphVault, + password: Option, + ) -> (Self, mpsc::UnboundedReceiver) { let (canary_tx, canary_rx) = oneshot::channel(); let (event_tx, event_rx) = mpsc::unbounded_channel(); let (euph_room_event_tx, euph_room_event_rx) = mpsc::unbounded_channel(); @@ -419,6 +430,7 @@ impl Room { let state = State { name: vault.room().to_string(), + password, vault, conn_tx: None, last_msg_id: None, diff --git a/src/main.rs b/src/main.rs index eb6c135..387d30d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -110,19 +110,21 @@ async fn main() -> anyhow::Result<()> { let mut config = Config::load(&config_path); set_data_dir(&mut config, args.data_dir); set_ephemeral(&mut config, args.ephemeral); + let config = Box::leak(Box::new(config)); let vault = if config.ephemeral { vault::launch_in_memory()? } else { let data_dir = config .data_dir + .clone() .unwrap_or_else(|| dirs.data_dir().to_path_buf()); println!("Data dir: {}", data_dir.to_string_lossy()); vault::launch(&data_dir.join("vault.db"))? }; match args.command.unwrap_or_default() { - Command::Run => run(&vault, args.measure_widths).await?, + Command::Run => run(config, &vault, args.measure_widths).await?, Command::Export(args) => export::export(&vault, args).await?, Command::Gc => { println!("Cleaning up and compacting vault"); @@ -141,7 +143,7 @@ async fn main() -> anyhow::Result<()> { Ok(()) } -async fn run(vault: &Vault, measure_widths: bool) -> anyhow::Result<()> { +async fn run(config: &'static Config, vault: &Vault, measure_widths: bool) -> anyhow::Result<()> { let (logger, logger_rx) = Logger::init(log::Level::Debug); info!( "Welcome to {} {}", @@ -151,7 +153,7 @@ async fn run(vault: &Vault, measure_widths: bool) -> anyhow::Result<()> { let mut terminal = Terminal::new()?; terminal.set_measuring(measure_widths); - Ui::run(&mut terminal, vault.clone(), logger, logger_rx).await?; + Ui::run(config, &mut terminal, vault.clone(), logger, logger_rx).await?; drop(terminal); // So the vault can print again Ok(()) diff --git a/src/ui.rs b/src/ui.rs index cc2035d..ddca402 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -17,6 +17,7 @@ use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender}; use tokio::task; use toss::terminal::Terminal; +use crate::config::Config; use crate::euph::EuphRoomEvent; use crate::logger::{LogMsg, Logger}; use crate::macros::{ok_or_return, some_or_return}; @@ -66,6 +67,7 @@ impl Ui { const POLL_DURATION: Duration = Duration::from_millis(100); pub async fn run( + config: &'static Config, terminal: &mut Terminal, vault: Vault, logger: Logger, @@ -93,7 +95,7 @@ impl Ui { let mut ui = Self { event_tx: event_tx.clone(), mode: Mode::Main, - rooms: Rooms::new(vault, event_tx.clone()), + rooms: Rooms::new(config, vault, event_tx.clone()), log_chat: ChatState::new(logger), key_bindings_list: None, }; diff --git a/src/ui/euph/room.rs b/src/ui/euph/room.rs index 78baa80..2700b1d 100644 --- a/src/ui/euph/room.rs +++ b/src/ui/euph/room.rs @@ -11,6 +11,7 @@ use tokio::sync::{mpsc, oneshot}; use toss::styled::Styled; use toss::terminal::Terminal; +use crate::config; use crate::euph::{self, EuphRoomEvent}; use crate::macros::{ok_or_return, some_or_return}; use crate::store::MsgStore; @@ -47,6 +48,8 @@ pub enum RoomStatus { } pub struct EuphRoom { + config: config::EuphRoom, + ui_event_tx: mpsc::UnboundedSender, vault: EuphVault, @@ -62,8 +65,13 @@ pub struct EuphRoom { } impl EuphRoom { - pub fn new(vault: EuphVault, ui_event_tx: mpsc::UnboundedSender) -> Self { + pub fn new( + config: config::EuphRoom, + vault: EuphVault, + ui_event_tx: mpsc::UnboundedSender, + ) -> Self { Self { + config, ui_event_tx, vault: vault.clone(), room: None, @@ -94,7 +102,7 @@ impl EuphRoom { if self.room.is_none() { let store = self.chat.store().clone(); let name = store.room().to_string(); - let (room, euph_room_event_rx) = euph::Room::new(store); + let (room, euph_room_event_rx) = euph::Room::new(store, self.config.password.clone()); self.room = Some(room); diff --git a/src/ui/rooms.rs b/src/ui/rooms.rs index 59d21bb..8d1d4ee 100644 --- a/src/ui/rooms.rs +++ b/src/ui/rooms.rs @@ -11,6 +11,7 @@ use tokio::sync::mpsc; use toss::styled::Styled; use toss::terminal::Terminal; +use crate::config::Config; use crate::euph::EuphRoomEvent; use crate::vault::Vault; @@ -33,6 +34,8 @@ enum State { } pub struct Rooms { + config: &'static Config, + vault: Vault, ui_event_tx: mpsc::UnboundedSender, @@ -43,8 +46,13 @@ pub struct Rooms { } impl Rooms { - pub fn new(vault: Vault, ui_event_tx: mpsc::UnboundedSender) -> Self { + pub fn new( + config: &'static Config, + vault: Vault, + ui_event_tx: mpsc::UnboundedSender, + ) -> Self { Self { + config, vault, ui_event_tx, state: State::ShowList, @@ -54,9 +62,13 @@ impl Rooms { } fn get_or_insert_room(&mut self, name: String) -> &mut EuphRoom { - self.euph_rooms - .entry(name.clone()) - .or_insert_with(|| EuphRoom::new(self.vault.euph(name), self.ui_event_tx.clone())) + self.euph_rooms.entry(name.clone()).or_insert_with(|| { + EuphRoom::new( + self.config.euph_room(&name), + self.vault.euph(name), + self.ui_event_tx.clone(), + ) + }) } /// Remove rooms that are not running any more and can't be found in the db.