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:
parent
10bd1853ed
commit
0f9c6f1e07
3
Gemfile
3
Gemfile
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) }
|
||||||
|
|
|
@ -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!"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue