|
@ -59,7 +59,7 @@ fn send_email_login(data: JsonUpcase<SendEmailLoginData>, conn: DbConn) -> Empty |
|
|
let type_ = TwoFactorType::Email as i32; |
|
|
let type_ = TwoFactorType::Email as i32; |
|
|
let mut twofactor = TwoFactor::find_by_user_and_type(&user.uuid, type_, &conn)?; |
|
|
let mut twofactor = TwoFactor::find_by_user_and_type(&user.uuid, type_, &conn)?; |
|
|
|
|
|
|
|
|
let generated_token = generate_token(CONFIG.email_token_size()); |
|
|
let generated_token = generate_token(CONFIG.email_token_size())?; |
|
|
let mut twofactor_data = EmailTokenData::from_json(&twofactor.data)?; |
|
|
let mut twofactor_data = EmailTokenData::from_json(&twofactor.data)?; |
|
|
twofactor_data.set_token(generated_token); |
|
|
twofactor_data.set_token(generated_token); |
|
|
twofactor.data = twofactor_data.to_json(); |
|
|
twofactor.data = twofactor_data.to_json(); |
|
@ -101,14 +101,20 @@ struct SendEmailData { |
|
|
MasterPasswordHash: String, |
|
|
MasterPasswordHash: String, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
fn generate_token(token_size: u64) -> String { |
|
|
|
|
|
crypto::get_random(vec![0; token_size as usize]) |
|
|
fn generate_token(token_size: u32) -> Result<String, Error> { |
|
|
.iter() |
|
|
if token_size > 19 { |
|
|
.map(|byte| { (byte % 10)}) |
|
|
err!("Generating token failed") |
|
|
.map(|num| { |
|
|
} |
|
|
char::from_digit(num as u32, 10).unwrap() |
|
|
|
|
|
}) |
|
|
// 8 bytes to create an u64 for up to 19 token digits
|
|
|
.collect() |
|
|
let bytes = crypto::get_random(vec![0; 8]); |
|
|
|
|
|
let mut bytes_array = [0u8; 8]; |
|
|
|
|
|
bytes_array.copy_from_slice(&bytes); |
|
|
|
|
|
|
|
|
|
|
|
let number = u64::from_be_bytes(bytes_array) % 10u64.pow(token_size); |
|
|
|
|
|
let token = format!("{:0size$}", number, size = token_size as usize); |
|
|
|
|
|
Ok(token) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// Send a verification email to the specified email address to check whether it exists/belongs to user.
|
|
|
/// Send a verification email to the specified email address to check whether it exists/belongs to user.
|
|
@ -131,7 +137,7 @@ fn send_email(data: JsonUpcase<SendEmailData>, headers: Headers, conn: DbConn) - |
|
|
tf.delete(&conn)?; |
|
|
tf.delete(&conn)?; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
let generated_token = generate_token(CONFIG.email_token_size()); |
|
|
let generated_token = generate_token(CONFIG.email_token_size())?; |
|
|
let twofactor_data = EmailTokenData::new(data.Email, generated_token); |
|
|
let twofactor_data = EmailTokenData::new(data.Email, generated_token); |
|
|
|
|
|
|
|
|
// Uses EmailVerificationChallenge as type to show that it's not verified yet.
|
|
|
// Uses EmailVerificationChallenge as type to show that it's not verified yet.
|
|
@ -321,8 +327,15 @@ mod tests { |
|
|
|
|
|
|
|
|
#[test] |
|
|
#[test] |
|
|
fn test_token() { |
|
|
fn test_token() { |
|
|
let result = generate_token(100); |
|
|
let result = generate_token(19).unwrap(); |
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(result.chars().count(), 19); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
|
|
fn test_token_too_large() { |
|
|
|
|
|
let result = generate_token(20); |
|
|
|
|
|
|
|
|
assert_eq!(result.chars().count(), 100); |
|
|
assert!(result.is_err(), "too large token should give an error"); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|