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

View File

@ -14,7 +14,10 @@ use std::io;
/// Runs the TUI and returns the entered username and password.
/// 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()?;
let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen)?;
@ -22,6 +25,8 @@ pub fn run() -> io::Result<(String, String)> {
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
let mut error_msg: Option<&str> = None;
let mut username = String::new();
let mut password = String::new();
let mut focus = 0;
@ -30,7 +35,11 @@ pub fn run() -> io::Result<(String, String)> {
terminal.draw(|f| {
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Length(3), Constraint::Length(3)])
.constraints([
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(2),
])
.split(f.area());
let user = Paragraph::new(username.as_str())
@ -51,8 +60,11 @@ pub fn run() -> io::Result<(String, String)> {
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(pass, chunks[1]);
f.render_widget(error, chunks[2]);
})?;
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::Enter => {
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()?;
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
Ok((username, password))
Ok(username)
}