From f3e2a0cb8333972d8f267a7873bfff27621ed5e0 Mon Sep 17 00:00:00 2001 From: Lucas Vas Date: Wed, 14 Jan 2026 08:42:07 -0500 Subject: [PATCH] feat: implement new email validation system --- src/components/text_field.rs | 33 +++++++++++++++++++++------------ src/pages/home_page.rs | 4 +++- src/pages/loaner_page.rs | 2 +- src/pages/provider_contact.rs | 2 +- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/components/text_field.rs b/src/components/text_field.rs index 5e831c1..dee1854 100644 --- a/src/components/text_field.rs +++ b/src/components/text_field.rs @@ -13,9 +13,15 @@ pub enum TextFieldType { Text, /// A text field that accepts only numbers. Number, - /// A text field that accepts only Region 15 email addresses. - /// TODO Accept more than just Region 15 addresses. - Email + /// A text field that accepts the specified email domains. + /// Values should be given as the string following the '@' in an address, or '*' for any. + /// + /// Example usage: + /// ``` + /// TextFieldType::Email(vec!["gmail.com".to_string(), "customdomain.org".to_string()]); + /// TextFieldType::Email(vec!["*".to_string()]); + /// ``` + Email(Vec) } /// Entry point for validating a text field. @@ -24,7 +30,7 @@ fn validate(required: bool, value: &str, input_type: &TextFieldType) -> Validati ValidationState::Invalid("This field is required.".to_string()) } else { match input_type { - TextFieldType::Email => validate_email(value), + TextFieldType::Email(domains) => validate_email(value, domains), TextFieldType::Number => validate_number(value), TextFieldType::Text => ValidationState::Valid } @@ -32,15 +38,18 @@ fn validate(required: bool, value: &str, input_type: &TextFieldType) -> Validati } /// Validates an email address. -fn validate_email(input: &str) -> ValidationState { - // TODO Accept more than just Region 15 addresses. - let pattern = regex::Regex::new(r"^[a-zA-Z0-9._%+-]+@region15\.org$").expect("Invalid regex pattern"); +fn validate_email(input: &str, valid_domains: &Vec) -> ValidationState { + // Check for wildcard domain. We won't check domains if it's present. + let wild = valid_domains.contains(&"*".to_string()); - if pattern.is_match(input) { - ValidationState::Valid - } else { - ValidationState::Invalid("Please provide a valid Region 15 email address.".to_string()) - } + input.split_once('@') + .and_then(|(_, domain)| { + (wild || valid_domains.contains(&domain.to_string())) + .then(|| ValidationState::Valid) + .or_else(|| Some(ValidationState::Invalid( + format!("Email address must match one of the following: {}", valid_domains.join(", ")) + ))) + }).unwrap_or(ValidationState::Invalid("Invalid email address.".to_string())) } /// Validates a number. diff --git a/src/pages/home_page.rs b/src/pages/home_page.rs index b708f36..6c47dcc 100644 --- a/src/pages/home_page.rs +++ b/src/pages/home_page.rs @@ -285,7 +285,9 @@ pub fn HomePage() -> impl IntoView { disabled=elements_disabled data_member="contact_email" data_map=form_data - input_type=TextFieldType::Email + input_type=TextFieldType::Email( + vec!["fakeemail.org".to_string(), "gmail.com".to_string()] + ) required=true /> diff --git a/src/pages/loaner_page.rs b/src/pages/loaner_page.rs index f165956..07b2464 100644 --- a/src/pages/loaner_page.rs +++ b/src/pages/loaner_page.rs @@ -328,7 +328,7 @@ pub fn LoanerBorrowForm() -> impl IntoView { disabled=elements_disabled data_member="email" data_map=data - input_type=TextFieldType::Email + input_type=TextFieldType::Email(vec!["region15.org".to_string()]) required=true /> diff --git a/src/pages/provider_contact.rs b/src/pages/provider_contact.rs index a874036..94b8cf7 100644 --- a/src/pages/provider_contact.rs +++ b/src/pages/provider_contact.rs @@ -178,7 +178,7 @@ pub fn ProviderContactPage() -> impl IntoView { disabled=elements_disabled data_member="contact_email" data_map=contact_info - input_type=TextFieldType::Email + input_type=TextFieldType::Email(vec!["*".to_string()]) required=true />