diff --git a/src/authfile.rs b/src/authfile.rs index 1e23e3c..7b19727 100644 --- a/src/authfile.rs +++ b/src/authfile.rs @@ -1,3 +1,4 @@ +use std::collections::HashSet; use std::io::{BufRead, BufReader}; use std::path::Path; use std::sync::Arc; @@ -5,10 +6,10 @@ use thiserror::Error; use russh::keys::PublicKey; use russh::keys::ssh_key::public::KeyData; -pub async fn read(path: &Path) -> Result>, Error> { +pub async fn read(path: &Path) -> Result { let handle = std::fs::File::open(path)?; let reader = BufReader::new(handle); - let mut keys = vec![]; + let mut entities = vec![]; for line in reader.lines() { let line = line?; let key = PublicKey::from_openssh(&line)?; @@ -27,9 +28,19 @@ pub async fn read(path: &Path) -> Result>, Error> { role, key, }; - keys.push(authorized_entity.into()); + entities.push(authorized_entity.into()); } - Ok(keys) + let key_pool = build_key_data_pool(&entities); + Ok(AuthFile { entities, key_pool }) +} + +fn build_key_data_pool(entities: &[Arc]) -> HashSet { + entities.iter().map(|e| e.key_data()).collect() +} + +pub struct AuthFile { + pub entities: Vec>, + pub key_pool: HashSet, } #[derive(Clone)] diff --git a/src/main.rs b/src/main.rs index aca0027..dc0bcbf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,10 +20,6 @@ mod authfile; type SshTerminal = Terminal>; -fn build_key_data_pool(entities: &[Arc]) -> HashSet { - entities.iter().map(|e| e.key_data()).collect() -} - // wraps a type T as Arc> so that it can be locked // in asynchronous coroutines fn new_atomic(object: T) -> Atomic { @@ -145,7 +141,6 @@ impl AppServer { async fn reload(&mut self) -> Result<(), Error> { let new_keychain = authfile::read(Path::new("./authfile")).await?; - let new_key_data_pool = build_key_data_pool(&new_keychain); // freeze all maps in the server state { @@ -157,7 +152,7 @@ impl AppServer { let mut id_to_user = self.id_to_user.lock().await; // find all strays - for stray in key_data_pool.difference(&new_key_data_pool) { + for stray in key_data_pool.difference(&new_keychain.key_pool) { let Some(ids) = key_data_to_id.get(stray) else { continue; }; @@ -175,11 +170,12 @@ impl AppServer { } *key_data_to_user = new_keychain + .entities .iter() .map(|e| (e.key_data(), e.clone())) .collect(); - *keychain = new_keychain; - *key_data_pool = new_key_data_pool; + *keychain = new_keychain.entities; + *key_data_pool = new_keychain.key_pool; } log::info!("authfile synchronized to memory"); Ok(()) @@ -225,7 +221,6 @@ impl AppServer { let area = f.area(); f.render_widget(Clear, area); - // split vertically as 80-20 let layout = Layout::default() .direction(Direction::Vertical) .constraints(vec![Constraint::Fill(1), Constraint::Length(4)]) @@ -237,14 +232,7 @@ impl AppServer { .map(|message| Text::styled(message.to_string(), style)) .collect(); - let paragraphs = - List::new(paragraphs).block(Block::bordered().title("chat")); - - // let block = Block::default() - // .title("chat") - // .borders(Borders::ALL); - - // f.render_widget(paragraph.block(block), area); + let paragraphs = List::new(paragraphs); f.render_widget(paragraphs, layout[0]); f.render_widget(&*textarea, layout[1]); }) @@ -288,12 +276,24 @@ impl Handler for AppServer { }; let terminal = Terminal::with_options(backend, options).unwrap(); + let title = { + let entity = self.entity().await; + let role = if entity.role() == authfile::Role::Admin { + "-[admin]" + } else { + "" + }; + format!("[{}]{}", entity.name(), role) + }; + + let mut textarea = TextArea::default(); + textarea.set_block(Block::bordered().title(title)); let mut clients = self.clients.lock().await; clients.insert( self.id, Client { - textarea: TextArea::default(), + textarea, channel, handle, terminal, @@ -431,12 +431,18 @@ async fn main() { .init(); let keychain = authfile::read(Path::new("./authfile")).await.unwrap(); - let key_data_pool = new_atomic(build_key_data_pool(&keychain)); + let key_data_pool = new_atomic(keychain.key_pool); let key_data_to_id = new_atomic(HashMap::new()); let id_to_user = new_atomic(HashMap::new()); let clients = new_atomic(HashMap::new()); - let key_data_to_user = new_atomic(keychain.iter().map(|e| (e.key_data(), e.clone())).collect()); - let keychain = new_atomic(keychain); + let key_data_to_user = new_atomic( + keychain + .entities + .iter() + .map(|e| (e.key_data(), e.clone())) + .collect(), + ); + let keychain = new_atomic(keychain.entities); let mut sh = AppServer { app: new_atomic(App::default()),