diff --git a/Cargo.toml b/Cargo.toml index 2f3aa0a..dc8e257 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,5 +8,6 @@ name = "breadm" path = "src/main.rs" [dependencies] +crossterm = "0.29.0" pam = "0.8.0" ratatui = "0.30.0" diff --git a/src/main.rs b/src/main.rs index f090720..699cffc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,85 @@ -mod auth; - +use crossterm::{ + event::{self, Event, KeyCode}, + execute, + terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode}, +}; +use ratatui::{ + Terminal, + backend::CrosstermBackend, + layout::{Constraint, Direction, Layout}, + style::{Color, Style}, + widgets::{Block, Borders, Paragraph}, +}; use std::io; -fn main() { +fn main() -> io::Result<()> { + enable_raw_mode()?; + let mut stdout = io::stdout(); + execute!(stdout, EnterAlternateScreen)?; + + let backend = CrosstermBackend::new(stdout); + let mut terminal = Terminal::new(backend)?; + let mut username = String::new(); let mut password = String::new(); + let mut focus = 0; // 0 user, 1 password - println!("username:"); - io::stdin().read_line(&mut username).unwrap(); + loop { + terminal.draw(|f| { + let chunks = Layout::default() + .direction(Direction::Vertical) + .constraints([Constraint::Length(3), Constraint::Length(3)]) + .split(f.area()); - println!("password:"); - io::stdin().read_line(&mut password).unwrap(); + let user = Paragraph::new(username.as_str()) + .block(Block::default().borders(Borders::ALL).title("User")) + .style(if focus == 0 { + Style::new().fg(Color::from_u32(0x00235759)) + } else { + Style::default() + }); - let username = username.trim(); - let password = password.trim(); + let pass = Paragraph::new(password.as_str()) + .block(Block::default().borders(Borders::ALL).title("Password")) + .style(if focus == 1 { + Style::new().fg(Color::from_u32(0x00235759)) + } else { + Style::default() + }); - match auth::authenticate(username, password) { - Ok(()) => println!("authentication successful"), - Err(e) => eprintln!("authentication failed: {e}"), + f.render_widget(user, chunks[0]); + f.render_widget(pass, chunks[1]); + })?; + + if let Event::Key(key) = event::read()? { + match key.code { + KeyCode::Esc => break, + KeyCode::Tab => focus = (focus + 1) % 2, + KeyCode::Enter => break, + KeyCode::Backspace => { + if focus == 0 { + username.pop(); + } else { + password.pop(); + } + } + KeyCode::Char(c) => { + if focus == 0 { + username.push(c); + } else { + password.push(c); + } + } + _ => {} + } + } } + + disable_raw_mode()?; + execute!(terminal.backend_mut(), LeaveAlternateScreen)?; + + println!("user = {username}"); + println!("pass = {password}"); + + Ok(()) }