|
| 1 | +use mongodb::bson::{Document, doc}; |
| 2 | +use mongodb::{Client, Collection}; |
| 3 | +use std::env; |
| 4 | +use std::error::Error; |
| 5 | + |
| 6 | +/// Checks if an email address uses a role-based alias by querying a MongoDB collection. |
| 7 | +/// |
| 8 | +/// # Arguments |
| 9 | +/// * `email` - A string slice containing the email address to check |
| 10 | +/// |
| 11 | +/// # Returns |
| 12 | +/// * `Ok(true)` if the alias is found in the role-based alias collection |
| 13 | +/// * `Ok(false)` if the alias is not found |
| 14 | +/// * `Err` containing an error message if any step fails |
| 15 | +/// |
| 16 | +/// # Errors |
| 17 | +/// Returns an error if: |
| 18 | +/// - The email is missing '@' symbol (invalid format) |
| 19 | +/// - Environment variables are not properly configured |
| 20 | +/// - MongoDB connection or query fails |
| 21 | +/// |
| 22 | +/// # Example |
| 23 | +/// ``` |
| 24 | +/// # async fn example() -> Result<(), Box<dyn std::error::Error>> { |
| 25 | +/// use email_sanitizer::handlers::validation::role_based::is_role_based_alias; |
| 26 | +/// let is_role_alias = is_role_based_alias("admin@example.com").await?; |
| 27 | +/// assert_eq!(is_role_alias, true); |
| 28 | +/// # Ok(()) |
| 29 | +/// # } |
| 30 | +/// ``` |
| 31 | +pub async fn is_role_based_alias(email: &str) -> Result<bool, Box<dyn Error>> { |
| 32 | + // Extract alias from email |
| 33 | + let (alias_part, _) = email |
| 34 | + .split_once('@') |
| 35 | + .ok_or("Invalid email format: missing '@'")?; |
| 36 | + let alias = alias_part.to_lowercase(); |
| 37 | + |
| 38 | + // Retrieve environment variables |
| 39 | + let mongo_uri = env::var("MONGODB_URI")?; |
| 40 | + let db_name = env::var("DB_NAME_PRODUCTION")?; |
| 41 | + let collection_name = env::var("DB_ROLE_BASED_ALIAS_COLLECTION")?; |
| 42 | + |
| 43 | + // Connect to MongoDB |
| 44 | + let client = Client::with_uri_str(&mongo_uri).await?; |
| 45 | + let database = client.database(&db_name); |
| 46 | + let collection: Collection<Document> = database.collection(&collection_name); |
| 47 | + |
| 48 | + // Check if alias exists in the collection |
| 49 | + let filter = doc! { "alias": alias }; |
| 50 | + let exists = collection.find_one(filter).await?.is_some(); |
| 51 | + |
| 52 | + Ok(exists) |
| 53 | +} |
| 54 | + |
| 55 | +#[cfg(test)] |
| 56 | +mod tests { |
| 57 | + use super::*; |
| 58 | + use mongodb::bson::{Document, doc}; |
| 59 | + use std::env; |
| 60 | + |
| 61 | + /// Helper function to set up test MongoDB collection |
| 62 | + async fn setup_collection() -> Collection<Document> { |
| 63 | + // Load environment variables from .env file |
| 64 | + dotenv::dotenv().ok(); |
| 65 | + |
| 66 | + let mongo_uri = env::var("MONGODB_URI").expect("MONGODB_URI must be set"); |
| 67 | + let db_name = env::var("DB_NAME_TEST").expect("DB_NAME_TEST must be set"); |
| 68 | + let collection_name = env::var("DB_ROLE_BASED_ALIAS_COLLECTION") |
| 69 | + .expect("DB_ROLE_BASED_ALIAS_COLLECTION must be set"); |
| 70 | + |
| 71 | + let client = Client::with_uri_str(&mongo_uri) |
| 72 | + .await |
| 73 | + .expect("Failed to connect to MongoDB"); |
| 74 | + client.database(&db_name).collection(&collection_name) |
| 75 | + } |
| 76 | + |
| 77 | + #[tokio::test] |
| 78 | + /// Tests recognition of role-based email aliases |
| 79 | + async fn test_role_based_alias() { |
| 80 | + let collection = setup_collection().await; |
| 81 | + |
| 82 | + // Insert test role-based alias |
| 83 | + collection |
| 84 | + .insert_one(doc! { "alias": "admin" }) |
| 85 | + .await |
| 86 | + .expect("Failed to insert test data"); |
| 87 | + |
| 88 | + // Test role-based alias |
| 89 | + let result = is_role_based_alias("admin@example.com").await; |
| 90 | + assert!(result.unwrap(), "Should recognize role-based alias"); |
| 91 | + |
| 92 | + // Cleanup |
| 93 | + collection |
| 94 | + .delete_many(doc! { "alias": "admin" }) |
| 95 | + .await |
| 96 | + .expect("Failed to clean up test data"); |
| 97 | + } |
| 98 | + |
| 99 | + #[tokio::test] |
| 100 | + /// Tests recognition of non-role-based email aliases |
| 101 | + async fn test_non_role_based_alias() { |
| 102 | + let collection = setup_collection().await; |
| 103 | + |
| 104 | + // Ensure test alias is removed |
| 105 | + collection |
| 106 | + .delete_many(doc! { "alias": "johndoe" }) |
| 107 | + .await |
| 108 | + .expect("Failed to clean up test data"); |
| 109 | + |
| 110 | + // Test valid email |
| 111 | + let result = is_role_based_alias("johndoe@gmail.com").await; |
| 112 | + assert!(!result.unwrap(), "Should recognize non-role-based alias"); |
| 113 | + } |
| 114 | +} |
0 commit comments