From 0f9c6f1e0766619605705734fc2dfbf3d6d89d75 Mon Sep 17 00:00:00 2001 From: Georg Gadinger Date: Thu, 13 Oct 2022 21:23:12 +0200 Subject: [PATCH] typoed_email_validator: check for valid TLDs i'm sure there are many more typos waiting to happen. one thing we can already catch though is the usage of invalid TLDs. this makes use of my new TLDv gem -- the data it uses can be updated independently from the main gem. --- Gemfile | 3 +++ Gemfile.lock | 4 ++++ app/validators/typoed_email_validator.rb | 17 +++++++++-------- .../user/registration_controller_spec.rb | 6 +++--- spec/models/user_spec.rb | 1 + 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/Gemfile b/Gemfile index 880832ce..b63d1937 100644 --- a/Gemfile +++ b/Gemfile @@ -65,6 +65,9 @@ gem "redis" gem "fake_email_validator" +# TLD validation +gem "tldv", "~> 0.1.0" + gem "jwt", "~> 2.5" group :development do diff --git a/Gemfile.lock b/Gemfile.lock index d18ddfac..43bd3c94 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -518,6 +518,9 @@ GEM thread_safe (0.3.6) tilt (2.0.11) timeout (0.3.0) + tldv (0.1.0) + tldv-data (~> 1.0) + tldv-data (1.0.2022101300) turbo-rails (1.1.1) actionpack (>= 6.0.0) activejob (>= 6.0.0) @@ -641,6 +644,7 @@ DEPENDENCIES simplecov-cobertura simplecov-json spring (~> 4.1) + tldv (~> 0.1.0) turbo-rails twitter twitter-text diff --git a/app/validators/typoed_email_validator.rb b/app/validators/typoed_email_validator.rb index 279c4950..8131bb48 100644 --- a/app/validators/typoed_email_validator.rb +++ b/app/validators/typoed_email_validator.rb @@ -1,15 +1,10 @@ # frozen_string_literal: true +require "tldv" + class TypoedEmailValidator < ActiveModel::EachValidator # this array contains "forbidden" email address endings INVALID_ENDINGS = [ - # without @: - ".carrd", - ".con", - ".coom", - ".cmo", - ".mail", - # with @: *%w[ fmail.com @@ -50,7 +45,13 @@ class TypoedEmailValidator < ActiveModel::EachValidator return false unless value.include?("@") # part after the @ needs to have at least one period - return false if value.split("@", 2).last.count(".").zero? + _prefix, domain = value.split("@", 2) + domain_parts = domain.split(".") + return false if domain_parts.length == 1 + + # check if the TLD is valid + tld = domain_parts.last + return false unless TLDv.valid?(tld) # finally, common typos return false if INVALID_ENDINGS.any? { value.end_with?(_1) } diff --git a/spec/controllers/user/registration_controller_spec.rb b/spec/controllers/user/registration_controller_spec.rb index 025e3edd..c31f5670 100644 --- a/spec/controllers/user/registration_controller_spec.rb +++ b/spec/controllers/user/registration_controller_spec.rb @@ -30,7 +30,7 @@ describe User::RegistrationsController, type: :controller do { user: { screen_name: "dio", - email: "the-world-21@somewhere.everywhere", + email: "the-world-21@somewhere.everywhere.now", password: "AReallySecurePassword456!", password_confirmation: "AReallySecurePassword456!" } @@ -85,7 +85,7 @@ describe User::RegistrationsController, type: :controller do { user: { screen_name: "Dio Brando", - email: "the-world-21@somewhere.everywhere", + email: "the-world-21@somewhere.everywhere.now", password: "AReallySecurePassword456!", password_confirmation: "AReallySecurePassword456!" } @@ -102,7 +102,7 @@ describe User::RegistrationsController, type: :controller do { user: { screen_name: "moderator", - email: "the-world-21@somewhere.everywhere", + email: "the-world-21@somewhere.everywhere.now", password: "AReallySecurePassword456!", password_confirmation: "AReallySecurePassword456!" } diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 5d12058f..d2714b22 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -64,6 +64,7 @@ RSpec.describe User, type: :model do include_examples "valid email", "fritz.fantom@protonmail.com" include_examples "valid email", "fritz.fantom@example.email" include_examples "valid email", "fritz.fantom@enterprise.k8s.420stripes.k8s.needs.more.k8s.jira.atlassian.k8s.eu-central-1.s3.amazonaws.com" + include_examples "valid email", "fritz.fantom@emacs.horse" include_examples "invalid email", "@jack" # examples from the real world: