pub mod config;
pub mod crypto;
pub mod manager;
pub mod types;
pub mod validation;
pub use config::AuthConfig;
pub use manager::AuthenticationManager;
pub use types::{AuthProvider, PasswordResetToken, User, UserSession};
#[cfg(test)]
mod tests {
use super::*;
use chrono::Utc;
#[tokio::test]
async fn test_user_registration() {
let auth_manager = AuthenticationManager::new();
let username = "test_user";
let password = "SecurePassword123!";
let email = "test@example.com";
let result = auth_manager.register_user(username, password, email).await;
assert!(result.is_ok());
let user_id = result.unwrap();
assert!(!user_id.is_empty());
}
#[tokio::test]
async fn test_user_login() {
let auth_manager = AuthenticationManager::new();
let username = "test_user";
let password = "SecurePassword123!";
let email = "test@example.com";
let user_id = auth_manager
.register_user(username, password, email)
.await
.unwrap();
let session = auth_manager.login(username, password).await.unwrap();
assert_eq!(session.user_id, user_id);
assert!(!session.token.is_empty());
assert!(session.expires_at > Utc::now());
}
#[tokio::test]
async fn test_invalid_login() {
let auth_manager = AuthenticationManager::new();
let username = "test_user";
let password = "SecurePassword123!";
let wrong_password = "WrongPassword123!";
auth_manager
.register_user(username, password, "test@example.com")
.await
.unwrap();
let result = auth_manager.login(username, wrong_password).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_session_validation() {
let auth_manager = AuthenticationManager::new();
let username = "test_user";
let password = "SecurePassword123!";
auth_manager
.register_user(username, password, "test@example.com")
.await
.unwrap();
let session = auth_manager.login(username, password).await.unwrap();
let is_valid = auth_manager.validate_session(&session.token).await.unwrap();
assert!(is_valid);
auth_manager.logout(&session.token).await.unwrap();
let is_valid_after_logout = auth_manager.validate_session(&session.token).await.unwrap();
assert!(!is_valid_after_logout);
}
#[tokio::test]
async fn test_password_reset() {
let auth_manager = AuthenticationManager::new();
let username = "test_user";
let old_password = "OldPassword123!";
let new_password = "NewPassword123!";
auth_manager
.register_user(username, old_password, "test@example.com")
.await
.unwrap();
let reset_token = auth_manager
.initiate_password_reset(username)
.await
.unwrap();
assert!(!reset_token.is_empty());
auth_manager
.complete_password_reset(&reset_token, new_password)
.await
.unwrap();
let old_login_result = auth_manager.login(username, old_password).await;
assert!(old_login_result.is_err());
let new_login_result = auth_manager.login(username, new_password).await;
assert!(new_login_result.is_ok());
}
#[tokio::test]
async fn test_multi_factor_authentication() {
let auth_manager = AuthenticationManager::new();
let username = "test_user";
let password = "SecurePassword123!";
let user_id = auth_manager
.register_user(username, password, "test@example.com")
.await
.unwrap();
auth_manager.enable_mfa(&user_id).await.unwrap();
let login_result = auth_manager.login(username, password).await;
assert!(login_result.is_err());
let mfa_code = auth_manager.generate_mfa_code(&user_id).await.unwrap();
let session = auth_manager
.login_with_mfa(username, password, &mfa_code)
.await
.unwrap();
assert!(!session.token.is_empty());
}
#[tokio::test]
async fn test_password_validation() {
let auth_manager = AuthenticationManager::new();
let weak_password = "123";
let result = auth_manager
.register_user("user1", weak_password, "test1@example.com")
.await;
assert!(result.is_err());
let no_upper = "password123!";
let result = auth_manager
.register_user("user2", no_upper, "test2@example.com")
.await;
assert!(result.is_err());
let no_lower = "PASSWORD123!";
let result = auth_manager
.register_user("user3", no_lower, "test3@example.com")
.await;
assert!(result.is_err());
let no_numbers = "Password!";
let result = auth_manager
.register_user("user4", no_numbers, "test4@example.com")
.await;
assert!(result.is_err());
let no_special = "Password123";
let result = auth_manager
.register_user("user5", no_special, "test5@example.com")
.await;
assert!(result.is_err());
let valid_password = "SecurePassword123!";
let result = auth_manager
.register_user("user6", valid_password, "test6@example.com")
.await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_account_lockout() {
let auth_manager = AuthenticationManager::new();
let username = "test_user";
let password = "SecurePassword123!";
let wrong_password = "WrongPassword123!";
auth_manager
.register_user(username, password, "test@example.com")
.await
.unwrap();
for _ in 0..5 {
let _ = auth_manager.login(username, wrong_password).await;
}
let result = auth_manager.login(username, password).await;
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("locked"));
}
#[tokio::test]
async fn test_duplicate_user_registration() {
let auth_manager = AuthenticationManager::new();
let username = "test_user";
let password = "SecurePassword123!";
let email = "test@example.com";
let result1 = auth_manager.register_user(username, password, email).await;
assert!(result1.is_ok());
let result2 = auth_manager.register_user(username, password, email).await;
assert!(result2.is_err());
assert!(result2.unwrap_err().to_string().contains("already exists"));
}
#[tokio::test]
async fn test_session_cleanup() {
let auth_manager = AuthenticationManager::new();
let username = "test_user";
let password = "SecurePassword123!";
auth_manager
.register_user(username, password, "test@example.com")
.await
.unwrap();
let session = auth_manager.login(username, password).await.unwrap();
let is_valid = auth_manager.validate_session(&session.token).await.unwrap();
assert!(is_valid);
let cleaned = auth_manager.cleanup_expired_sessions().await;
assert_eq!(cleaned, 0);
let is_valid_after_cleanup = auth_manager.validate_session(&session.token).await.unwrap();
assert!(is_valid_after_cleanup);
}
}