use crate::consts::{CV_DEFAULT_SIZE, CV_MAX_SIZE, CV_MIN_SIZE};
use crate::errors::CodeVerifierError;
use crate::urlsafe::{urlsafe_b64encode, urlsafe_token};
use sha2::{Digest, Sha256};
type CodeVerifierResult = Result<String, CodeVerifierError>;
pub fn gen_code_verifier(n: Option<usize>) -> CodeVerifierResult {
let size: usize = n.unwrap_or(CV_DEFAULT_SIZE);
if size > CV_MAX_SIZE {
return Err(CodeVerifierError::TooBig);
}
if size < CV_MIN_SIZE {
return Err(CodeVerifierError::TooSmall);
}
Ok(urlsafe_token(size))
}
pub fn gen_code_challenge(code_verifier: &str) -> String {
urlsafe_b64encode(Sha256::digest(code_verifier))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gen_code_verifier_default_size() {
let code_verifier_result: CodeVerifierResult = gen_code_verifier(None);
assert!(code_verifier_result.is_ok());
let code_verifier = code_verifier_result.unwrap();
assert_eq!(code_verifier.len(), CV_DEFAULT_SIZE);
}
#[test]
fn test_gen_code_verifier_custom_size_within_range() {
let custom_size: usize = 64;
let code_verifier_result: CodeVerifierResult =
gen_code_verifier(Some(custom_size));
assert!(code_verifier_result.is_ok());
let code_verifier = code_verifier_result.unwrap();
assert_eq!(code_verifier.len(), custom_size);
}
#[test]
fn test_gen_code_verifier_custom_size_too_small() {
let custom_size: usize = CV_MIN_SIZE - 1;
let code_verifier_result: CodeVerifierResult =
gen_code_verifier(Some(custom_size));
assert!(code_verifier_result.is_err()); let err = code_verifier_result.err().unwrap();
assert_eq!(err, CodeVerifierError::TooSmall);
}
#[test]
fn test_gen_code_verifier_custom_size_too_large() {
let custom_size: usize = CV_MAX_SIZE + 1;
let code_verifier_result: CodeVerifierResult =
gen_code_verifier(Some(custom_size));
assert!(code_verifier_result.is_err());
let err = code_verifier_result.err().unwrap();
assert_eq!(err, CodeVerifierError::TooBig);
}
#[test]
fn test_gen_code_challenge() {
let code_verifier: &str = "foo_bar";
let code_challenge: String = gen_code_challenge(code_verifier);
let mut hasher = Sha256::new();
hasher.update(code_verifier);
let hash_result = hasher.finalize();
let expected_challenge = urlsafe_b64encode(&hash_result);
assert_eq!(code_challenge, expected_challenge);
}
}