use crate::config::Config;
use ansi_term::Colour::Green;
use log::info;
use md5::compute;
use rand::Rng;
use std::fs;
use std::path::PathBuf;
pub fn gen(target: &PathBuf) {
if target.exists() {
info!("Target already exists");
return;
}
fs::create_dir_all(target).unwrap_or_else(|_| panic!("failed to generate {:?}", target));
info!("Creating path: {:?}", target);
let config = Config::default();
let config_str = serde_yaml::to_string(&config).unwrap();
let config_path = target.join("config.yml");
fs::write(config_path.clone(), config_str)
.unwrap_or_else(|_| panic!("failed to write {:?}", config_path));
info!("Generated: {:?}", config_path);
}
pub fn gen_password(length: u8, username: Option<String>, password: Option<String>) {
let password = match password {
Some(p) => p,
None => {
const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789)(*&^%$#@!~";
let mut rng = rand::thread_rng();
let password: String = (0..length)
.map(|_| {
let idx = rng.gen_range(0..CHARS.len());
CHARS[idx] as char
})
.collect();
password
}
};
println!("Generated password: {}", Green.paint(password.clone()));
if let Some(username) = username {
let password_hash = gen_md5_password(&password, &username);
println!(
"Generated MD5 (user: {}): {}",
username,
Green.paint(password_hash.clone())
);
println!("\nHint: https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_USER.html");
} else {
println!("\nHint: Please provide --username to generate MD5");
}
}
fn gen_md5_password(password: &str, username: &str) -> String {
format!(
"md5{:x}",
compute(format!("{}{}", password, username).as_bytes())
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gen_password() {
gen_password(10, None, None);
gen_password(10, Some("test".to_string()), None);
gen_password(10, Some("test".to_string()), Some("test".to_string()));
}
#[test]
fn test_gen_md5_password() {
assert_eq!(
gen_md5_password("test", "test"),
"md505a671c66aefea124cc08b76ea6d30bb"
);
}
}