use crate::cli::RupassArgs;
use crate::cli::UserInterface;
use crate::core::app_errors::Result;
use crate::crypto::global_rng::ByteStream;
use crate::password::character_set::assemble_character_set;
use crate::password::password_generation::{
GenerationOutcome, PasswordStrengthEvaluator, ZxcvbnEvaluator, produce_password_within_time,
validate_charset_feasibility,
};
use crate::password::password_length::get_password_length;
use crate::password::reporting::{FlowReport, build_header, build_strength_line, build_warnings};
use fluent::{FluentBundle, FluentResource};
#[doc(alias = "generate")]
pub async fn generate_password_flow(
ui: &mut dyn UserInterface,
bundle: &FluentBundle<FluentResource>,
args: &RupassArgs,
rng: &mut impl ByteStream,
) -> Result<FlowReport> {
generate_password_flow_internal(ui, bundle, args, args.min_score, &ZxcvbnEvaluator, rng).await
}
#[doc(alias = "generate")]
pub async fn generate_password_flow_with_evaluator(
ui: &mut dyn UserInterface,
bundle: &FluentBundle<FluentResource>,
args: &RupassArgs,
evaluator: &dyn PasswordStrengthEvaluator,
rng: &mut impl ByteStream,
) -> Result<FlowReport> {
generate_password_flow_internal(ui, bundle, args, args.min_score, evaluator, rng).await
}
pub async fn generate_password_flow_with_min_score(
ui: &mut dyn UserInterface,
bundle: &FluentBundle<FluentResource>,
args: &RupassArgs,
min_score: u8,
rng: &mut impl ByteStream,
) -> Result<FlowReport> {
generate_password_flow_internal(ui, bundle, args, min_score, &ZxcvbnEvaluator, rng).await
}
async fn generate_password_flow_internal(
ui: &mut dyn UserInterface,
bundle: &FluentBundle<FluentResource>,
args: &RupassArgs,
min_score: u8,
evaluator: &dyn PasswordStrengthEvaluator,
rng: &mut impl ByteStream,
) -> Result<FlowReport> {
let length = get_password_length(ui, bundle, args).await?;
let (all_chars, req_sets) = assemble_character_set(ui, bundle, args).await?;
let all_vec: Vec<char> = all_chars.chars().collect();
let req_vec: Vec<Vec<char>> = req_sets.iter().map(|s| s.chars().collect()).collect();
validate_charset_feasibility(&all_vec, &req_vec, length)?;
let outcome = produce_password_within_time(
rng,
&all_vec,
&req_vec,
length,
args.timeout_ms,
min_score,
args.strict,
evaluator,
)
.await;
let outcome = outcome?;
let GenerationOutcome {
password,
score,
entropy_bits,
reached_target,
} = outcome;
let header = build_header(bundle, args);
let strength_line = build_strength_line(bundle, args, score, entropy_bits);
let warnings = build_warnings(args, min_score, reached_target, score, entropy_bits);
Ok(FlowReport {
password,
header,
strength_line,
warnings,
reached_target,
score,
entropy_bits,
show_blank_line: !args.quiet,
})
}