| 
						
						
							
								
							
						
						
					 | 
					@ -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"); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
					 | 
					
  |