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.
This commit is contained in:
Georg Gadinger 2022-10-13 21:23:12 +02:00
parent 10bd1853ed
commit 0f9c6f1e07
5 changed files with 20 additions and 11 deletions

View File

@ -65,6 +65,9 @@ gem "redis"
gem "fake_email_validator" gem "fake_email_validator"
# TLD validation
gem "tldv", "~> 0.1.0"
gem "jwt", "~> 2.5" gem "jwt", "~> 2.5"
group :development do group :development do

View File

@ -518,6 +518,9 @@ GEM
thread_safe (0.3.6) thread_safe (0.3.6)
tilt (2.0.11) tilt (2.0.11)
timeout (0.3.0) timeout (0.3.0)
tldv (0.1.0)
tldv-data (~> 1.0)
tldv-data (1.0.2022101300)
turbo-rails (1.1.1) turbo-rails (1.1.1)
actionpack (>= 6.0.0) actionpack (>= 6.0.0)
activejob (>= 6.0.0) activejob (>= 6.0.0)
@ -641,6 +644,7 @@ DEPENDENCIES
simplecov-cobertura simplecov-cobertura
simplecov-json simplecov-json
spring (~> 4.1) spring (~> 4.1)
tldv (~> 0.1.0)
turbo-rails turbo-rails
twitter twitter
twitter-text twitter-text

View File

@ -1,15 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
require "tldv"
class TypoedEmailValidator < ActiveModel::EachValidator class TypoedEmailValidator < ActiveModel::EachValidator
# this array contains "forbidden" email address endings # this array contains "forbidden" email address endings
INVALID_ENDINGS = [ INVALID_ENDINGS = [
# without @:
".carrd",
".con",
".coom",
".cmo",
".mail",
# with @: # with @:
*%w[ *%w[
fmail.com fmail.com
@ -50,7 +45,13 @@ class TypoedEmailValidator < ActiveModel::EachValidator
return false unless value.include?("@") return false unless value.include?("@")
# part after the @ needs to have at least one period # 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 # finally, common typos
return false if INVALID_ENDINGS.any? { value.end_with?(_1) } return false if INVALID_ENDINGS.any? { value.end_with?(_1) }

View File

@ -30,7 +30,7 @@ describe User::RegistrationsController, type: :controller do
{ {
user: { user: {
screen_name: "dio", screen_name: "dio",
email: "the-world-21@somewhere.everywhere", email: "the-world-21@somewhere.everywhere.now",
password: "AReallySecurePassword456!", password: "AReallySecurePassword456!",
password_confirmation: "AReallySecurePassword456!" password_confirmation: "AReallySecurePassword456!"
} }
@ -85,7 +85,7 @@ describe User::RegistrationsController, type: :controller do
{ {
user: { user: {
screen_name: "Dio Brando", screen_name: "Dio Brando",
email: "the-world-21@somewhere.everywhere", email: "the-world-21@somewhere.everywhere.now",
password: "AReallySecurePassword456!", password: "AReallySecurePassword456!",
password_confirmation: "AReallySecurePassword456!" password_confirmation: "AReallySecurePassword456!"
} }
@ -102,7 +102,7 @@ describe User::RegistrationsController, type: :controller do
{ {
user: { user: {
screen_name: "moderator", screen_name: "moderator",
email: "the-world-21@somewhere.everywhere", email: "the-world-21@somewhere.everywhere.now",
password: "AReallySecurePassword456!", password: "AReallySecurePassword456!",
password_confirmation: "AReallySecurePassword456!" password_confirmation: "AReallySecurePassword456!"
} }

View File

@ -64,6 +64,7 @@ RSpec.describe User, type: :model do
include_examples "valid email", "fritz.fantom@protonmail.com" include_examples "valid email", "fritz.fantom@protonmail.com"
include_examples "valid email", "fritz.fantom@example.email" 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@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" include_examples "invalid email", "@jack"
# examples from the real world: # examples from the real world: