Loop TUI until successful auth

This commit is contained in:
Candifloss 2026-01-20 22:04:21 +05:30
parent a3569628e0
commit 281dddb19f
2 changed files with 22 additions and 15 deletions

View File

@ -4,16 +4,7 @@ mod tui;
use std::io; use std::io;
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let (username, password) = tui::run()?; let username = tui::run(|u, p| auth::authenticate(u, p).is_ok())?;
println!("authenticated as {username}");
match auth::authenticate(&username, &password) {
Ok(()) => {
println!("authentication successful");
}
Err(_) => {
println!("authentication failed");
}
}
Ok(()) Ok(())
} }

View File

@ -14,7 +14,10 @@ use std::io;
/// Runs the TUI and returns the entered username and password. /// Runs the TUI and returns the entered username and password.
/// This module owns all terminal state. /// This module owns all terminal state.
pub fn run() -> io::Result<(String, String)> { pub fn run<F>(auth_fn: F) -> io::Result<String>
where
F: Fn(&str, &str) -> bool,
{
enable_raw_mode()?; enable_raw_mode()?;
let mut stdout = io::stdout(); let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen)?; execute!(stdout, EnterAlternateScreen)?;
@ -22,6 +25,8 @@ pub fn run() -> io::Result<(String, String)> {
let backend = CrosstermBackend::new(stdout); let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?; let mut terminal = Terminal::new(backend)?;
let mut error_msg: Option<&str> = None;
let mut username = String::new(); let mut username = String::new();
let mut password = String::new(); let mut password = String::new();
let mut focus = 0; let mut focus = 0;
@ -30,7 +35,11 @@ pub fn run() -> io::Result<(String, String)> {
terminal.draw(|f| { terminal.draw(|f| {
let chunks = Layout::default() let chunks = Layout::default()
.direction(Direction::Vertical) .direction(Direction::Vertical)
.constraints([Constraint::Length(3), Constraint::Length(3)]) .constraints([
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(2),
])
.split(f.area()); .split(f.area());
let user = Paragraph::new(username.as_str()) let user = Paragraph::new(username.as_str())
@ -51,8 +60,11 @@ pub fn run() -> io::Result<(String, String)> {
Style::default() Style::default()
}); });
let error = Paragraph::new(error_msg.unwrap_or("")).style(Style::new().fg(Color::Red));
f.render_widget(user, chunks[0]); f.render_widget(user, chunks[0]);
f.render_widget(pass, chunks[1]); f.render_widget(pass, chunks[1]);
f.render_widget(error, chunks[2]);
})?; })?;
if let Event::Key(key) = event::read()? { if let Event::Key(key) = event::read()? {
@ -61,7 +73,11 @@ pub fn run() -> io::Result<(String, String)> {
KeyCode::Tab => focus = (focus + 1) % 2, KeyCode::Tab => focus = (focus + 1) % 2,
KeyCode::Enter => { KeyCode::Enter => {
if !username.is_empty() && !password.is_empty() { if !username.is_empty() && !password.is_empty() {
break; if auth_fn(&username, &password) {
break;
}
password.clear();
error_msg = Some("Authentication failed");
} }
} }
@ -87,5 +103,5 @@ pub fn run() -> io::Result<(String, String)> {
disable_raw_mode()?; disable_raw_mode()?;
execute!(terminal.backend_mut(), LeaveAlternateScreen)?; execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
Ok((username, password)) Ok(username)
} }