oauth-db-cli 0.1.0

Command-line tool for managing OAuth-DB platform
Documentation
use crate::auth;
use crate::cli::LoginArgs;
use crate::client::ApiClient;
use crate::config::Config;
use crate::error::Result;
use crate::output::{print_success};
use dialoguer::{Input, Password};

pub async fn execute(args: &LoginArgs) -> Result<()> {
    // Determine server URL
    let config = Config::load().unwrap_or_default();
    let server = args
        .server
        .clone()
        .or_else(|| Some(config.server.url.clone()))
        .unwrap_or_else(|| "http://localhost:38080".to_string());

    // Get username
    let username = if let Some(u) = &args.username {
        u.clone()
    } else {
        Input::new()
            .with_prompt("Username")
            .interact_text()
            .map_err(|e| crate::error::CliError::InvalidInput(format!("Failed to read username: {}", e)))?
    };

    // Get password
    let password = if let Some(p) = &args.password {
        p.clone()
    } else {
        Password::new()
            .with_prompt("Password")
            .interact()
            .map_err(|e| crate::error::CliError::InvalidInput(format!("Failed to read password: {}", e)))?
    };

    // Create API client and login
    let client = ApiClient::new(server.clone(), None)?;

    print!("Logging in... ");
    let login_response = client.login(&username, &password).await?;

    // Fetch user info to get role
    let client_with_token = ApiClient::new(server.clone(), Some(login_response.access_token.clone()))?;
    let user_info = client_with_token.get_me().await?;

    // Save account with role
    let account_name = format!("{}@{}", username, extract_host(&server));
    auth::save_account_with_role(
        account_name.clone(),
        server,
        username.clone(),
        login_response.access_token,
        user_info.role.clone(),
        true, // Set as default
    )
    .await?;

    print_success(&format!("Logged in as {} (role: {})", username, user_info.role));
    println!("Account saved as: {}", account_name);

    Ok(())
}

fn extract_host(url: &str) -> String {
    url.trim_start_matches("http://")
        .trim_start_matches("https://")
        .split(':')
        .next()
        .unwrap_or("localhost")
        .to_string()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_extract_host() {
        assert_eq!(extract_host("http://localhost:38080"), "localhost");
        assert_eq!(extract_host("https://api.example.com"), "api.example.com");
        assert_eq!(extract_host("http://192.168.1.1:8080"), "192.168.1.1");
    }
}