From c59dd97f198bc5cab09cb2c048217194edd5d3aa Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Sat, 31 Jan 2026 23:08:33 +0000 Subject: [PATCH] fix: resolve CI workflow path and add lint job --- src/main.rs | 375 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 src/main.rs diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..2d688f6 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,375 @@ +mod cli; +mod vault; +mod token; +mod rotation; +mod env_injector; +mod crypto; + +use cli::Cli; +use vault::Vault; +use crypto::CryptoManager; +use std::process; + +fn main() { + let cli = Cli::parse(); + + match cli.command { + cli::Commands::Init { master_password, project } => { + let password = master_password.unwrap_or_else(|| { + rpassword::prompt_password("Enter master password: ").unwrap_or_else(|_| { + eprintln!("Failed to read password"); + process::exit(1); + }) + }); + + let project_name = project.unwrap_or_else(|| { + "default".to_string() + }); + + match Vault::initialize(&password, &project_name) { + Ok(_) => println!("Vault initialized for project '{}'", project_name), + Err(e) => { + eprintln!("Failed to initialize vault: {}", e); + process::exit(1); + } + } + } + + cli::Commands::Generate { name, length, project, master_password } => { + let password = master_password.unwrap_or_else(|| { + rpassword::prompt_password("Enter master password: ").unwrap_or_else(|_| { + eprintln!("Failed to read password"); + process::exit(1); + }) + }); + + let project_name = project.unwrap_or_else(|| { + std::env::var("API_VAULT_PROJECT").unwrap_or_else(|_| "default".to_string()) + }); + + let token_length = length.unwrap_or(32); + + match Vault::load(&password, &project_name) { + Ok(mut vault) => { + match vault.generate_token(&name, token_length) { + Ok(generated_token) => { + match vault.save(&password) { + Ok(_) => println!("Generated token '{}': {}", name, generated_token), + Err(e) => { + eprintln!("Failed to save vault: {}", e); + process::exit(1); + } + } + } + Err(e) => { + eprintln!("Failed to generate token: {}", e); + process::exit(1); + } + } + } + Err(e) => { + eprintln!("Failed to load vault: {}", e); + process::exit(1); + } + } + } + + cli::Commands::List { project, master_password } => { + let password = master_password.unwrap_or_else(|| { + rpassword::prompt_password("Enter master password: ").unwrap_or_else(|_| { + eprintln!("Failed to read password"); + process::exit(1); + }) + }); + + let project_name = project.unwrap_or_else(|| { + std::env::var("API_VAULT_PROJECT").unwrap_or_else(|_| "default".to_string()) + }); + + match Vault::load(&password, &project_name) { + Ok(vault) => { + if vault.tokens.is_empty() { + println!("No tokens found in vault for project '{}'", project_name); + } else { + println!("Tokens in vault for project '{}':", project_name); + println!("{}", "-".repeat(50)); + for (name, token_data) in &vault.tokens { + println!(" Name: {}", name); + println!(" Created: {}", token_data.created_at); + if let Some(expires) = token_data.expires_at { + println!(" Expires: {}", expires); + } else { + println!(" Expires: Never"); + } + println!(" Rotated: {}", if token_data.auto_rotate { "Yes" } else { "No" }); + println!("{}", "-".repeat(50)); + } + } + } + Err(e) => { + eprintln!("Failed to load vault: {}", e); + process::exit(1); + } + } + } + + cli::Commands::Get { name, project, master_password, raw } => { + let password = master_password.unwrap_or_else(|| { + rpassword::prompt_password("Enter master password: ").unwrap_or_else(|_| { + eprintln!("Failed to read password"); + process::exit(1); + }) + }); + + let project_name = project.unwrap_or_else(|| { + std::env::var("API_VAULT_PROJECT").unwrap_or_else(|_| "default".to_string()) + }); + + match Vault::load(&password, &project_name) { + Ok(vault) => { + match vault.get_token(&name) { + Some(token_data) => { + if raw { + print!("{}", token_data.value); + } else { + println!("Token '{}': {}", name, token_data.value); + println!("Created: {}", token_data.created_at); + if let Some(expires) = &token_data.expires_at { + println!("Expires: {}", expires); + } + } + } + None => { + eprintln!("Token '{}' not found", name); + process::exit(1); + } + } + } + Err(e) => { + eprintln!("Failed to load vault: {}", e); + process::exit(1); + } + } + } + + cli::Commands::Delete { name, project, master_password } => { + let password = master_password.unwrap_or_else(|| { + rpassword::prompt_password("Enter master password: ").unwrap_or_else(|_| { + eprintln!("Failed to read password"); + process::exit(1); + }) + }); + + let project_name = project.unwrap_or_else(|| { + std::env::var("API_VAULT_PROJECT").unwrap_or_else(|_| "default".to_string()) + }); + + match Vault::load(&password, &project_name) { + Ok(mut vault) => { + match vault.remove_token(&name) { + Ok(_) => { + match vault.save(&password) { + Ok(_) => println!("Token '{}' deleted", name), + Err(e) => { + eprintln!("Failed to save vault: {}", e); + process::exit(1); + } + } + } + Err(e) => { + eprintln!("Failed to delete token: {}", e); + process::exit(1); + } + } + } + Err(e) => { + eprintln!("Failed to load vault: {}", e); + process::exit(1); + } + } + } + + cli::Commands::Rotate { name, project, master_password, force } => { + let password = master_password.unwrap_or_else(|| { + rpassword::prompt_password("Enter master password: ").unwrap_or_else(|_| { + eprintln!("Failed to read password"); + process::exit(1); + }) + }); + + let project_name = project.unwrap_or_else(|| { + std::env::var("API_VAULT_PROJECT").unwrap_or_else(|_| "default".to_string()) + }); + + match Vault::load(&password, &project_name) { + Ok(mut vault) => { + match vault.rotate_token(&name, force) { + Ok(new_value) => { + match vault.save(&password) { + Ok(_) => println!("Rotated token '{}': {}", name, new_value), + Err(e) => { + eprintln!("Failed to save vault: {}", e); + process::exit(1); + } + } + } + Err(e) => { + eprintln!("Failed to rotate token: {}", e); + process::exit(1); + } + } + } + Err(e) => { + eprintln!("Failed to load vault: {}", e); + process::exit(1); + } + } + } + + cli::Commands::SetRotation { name, days, project, master_password } => { + let password = master_password.unwrap_or_else(|| { + rpassword::prompt_password("Enter master password: ").unwrap_or_else(|_| { + eprintln!("Failed to read password"); + process::exit(1); + }) + }); + + let project_name = project.unwrap_or_else(|| { + std::env::var("API_VAULT_PROJECT").unwrap_or_else(|_| "default".to_string()) + }); + + match Vault::load(&password, &project_name) { + Ok(mut vault) => { + match vault.set_rotation(&name, days) { + Ok(_) => { + match vault.save(&password) { + Ok(_) => println!("Auto-rotation set for '{}': every {} days", name, days), + Err(e) => { + eprintln!("Failed to save vault: {}", e); + process::exit(1); + } + } + } + Err(e) => { + eprintln!("Failed to set rotation: {}", e); + process::exit(1); + } + } + } + Err(e) => { + eprintln!("Failed to load vault: {}", e); + process::exit(1); + } + } + } + + cli::Commands::Inject { env_file, token_prefix, project, master_password, dry_run } => { + let password = master_password.unwrap_or_else(|| { + rpassword::prompt_password("Enter master password: ").unwrap_or_else(|_| { + eprintln!("Failed to read password"); + process::exit(1); + }) + }); + + let project_name = project.unwrap_or_else(|| { + std::env::var("API_VAULT_PROJECT").unwrap_or_else(|_| "default".to_string()) + }); + + let env_path = env_file.unwrap_or_else(|| { + ".env".to_string() + }); + + match Vault::load(&password, &project_name) { + Ok(vault) => { + match env_injector::inject_tokens(&vault, &env_path, token_prefix, dry_run) { + Ok(()) => { + if dry_run { + println!("Dry run complete. No changes made."); + } else { + println!("Tokens injected into {}", env_path); + } + } + Err(e) => { + eprintln!("Failed to inject tokens: {}", e); + process::exit(1); + } + } + } + Err(e) => { + eprintln!("Failed to load vault: {}", e); + process::exit(1); + } + } + } + + cli::Commands::CheckExpired { project, master_password } => { + let password = master_password.unwrap_or_else(|| { + rpassword::prompt_password("Enter master password: ").unwrap_or_else(|_| { + eprintln!("Failed to read password"); + process::exit(1); + }) + }); + + let project_name = project.unwrap_or_else(|| { + std::env::var("API_VAULT_PROJECT").unwrap_or_else(|_| "default".to_string()) + }); + + match Vault::load(&password, &project_name) { + Ok(vault) => { + let expired = vault.check_expired_tokens(); + if expired.is_empty() { + println!("No expired tokens found"); + } else { + println!("Expired tokens:"); + for (name, token_data) in expired { + println!(" {} - expired at {}", name, token_data.expires_at.unwrap()); + } + } + } + Err(e) => { + eprintln!("Failed to load vault: {}", e); + process::exit(1); + } + } + } + + cli::Commands::RotateExpired { project, master_password } => { + let password = master_password.unwrap_or_else(|| { + rpassword::prompt_password("Enter master password: ").unwrap_or_else(|_| { + eprintln!("Failed to read password"); + process::exit(1); + }) + }); + + let project_name = project.unwrap_or_else(|| { + std::env::var("API_VAULT_PROJECT").unwrap_or_else(|_| "default".to_string()) + }); + + match Vault::load(&password, &project_name) { + Ok(mut vault) => { + let rotated = vault.rotate_expired_tokens(); + if rotated.is_empty() { + println!("No expired tokens to rotate"); + } else { + match vault.save(&password) { + Ok(_) => { + println!("Rotated {} expired token(s):", rotated.len()); + for name in rotated { + println!(" - {}", name); + } + } + Err(e) => { + eprintln!("Failed to save vault: {}", e); + process::exit(1); + } + } + } + } + Err(e) => { + eprintln!("Failed to load vault: {}", e); + process::exit(1); + } + } + } + } +}