Skip to content

Commit

Permalink
change: deprecate blacklist and whitelist naming, #205
Browse files Browse the repository at this point in the history
  • Loading branch information
ianbayne committed Aug 17, 2024
1 parent 38c11b4 commit 2782fe5
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 48 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,20 +73,20 @@ To validate that the domain is not a disposable email (checks domain only, does
validates :email, 'valid_email_2/email': { disposable_domain: true }
```

To validate that the domain is not a disposable email or a disposable email (checks domain and MX server) but whitelisted (under config/whitelisted_email_domains.yml):
To validate that the domain is not a disposable email or a disposable email (checks domain and MX server) but allow-listed (under config/allow_listed_email_domains.yml):
```ruby
validates :email, 'valid_email_2/email': { disposable_with_whitelist: true }
validates :email, 'valid_email_2/email': { disposable_with_allow_list: true }
```

To validate that the domain is not a disposable email or a disposable email (checks domain only, does not check MX server) but whitelisted (under config/whitelisted_email_domains.yml):
To validate that the domain is not a disposable email or a disposable email (checks domain only, does not check MX server) but allow-listed (under config/allow_listed_email_domains.yml):

```ruby
validates :email, 'valid_email_2/email': { disposable_domain_with_whitelist: true }
validates :email, 'valid_email_2/email': { disposable_domain_with_allow_list: true }
```

To validate that the domain is not blacklisted (under config/blacklisted_email_domains.yml):
To validate that the domain is not on the deny list (under config/deny_list_email_domains.yml):
```ruby
validates :email, 'valid_email_2/email': { blacklist: true }
validates :email, 'valid_email_2/email': { deny_list: true }
```

To validate that email is not subaddressed:
Expand Down
1 change: 0 additions & 1 deletion config/blacklisted_email_domains.yml

This file was deleted.

1 change: 1 addition & 0 deletions config/deny_listed_email_domains.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- deny-listed-test.com
12 changes: 12 additions & 0 deletions lib/helpers/deprecation_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module DeprecationHelper
def deprecate_method(old_method, new_method)
define_method(old_method) do |*args, &block|
warn "Warning: `#{old_method}` is deprecated; use `#{new_method}` instead."
send(new_method, *args, &block)
end
end

def deprecation_message(old_name, new_name)
warn "Warning: `#{old_name}` is deprecated; use `#{new_name}` instead."
end
end
14 changes: 12 additions & 2 deletions lib/valid_email2.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
# frozen_string_literal: true

require "valid_email2/email_validator"
require_relative "./helpers/deprecation_helper"

module ValidEmail2

BLACKLIST_FILE = "config/blacklisted_email_domains.yml"
DENY_LIST_FILE = "config/deny_listed_email_domains.yml"
WHITELIST_FILE = "config/whitelisted_email_domains.yml"
ALLOW_LIST_FILE = "config/allow_listed_email_domains.yml"
DISPOSABLE_FILE = File.expand_path('../config/disposable_email_domains.txt', __dir__)

class << self
extend DeprecationHelper

def disposable_emails
@disposable_emails ||= load_file(DISPOSABLE_FILE)
end

def blacklist
@blacklist ||= load_if_exists(BLACKLIST_FILE)
@deny_list ||= load_if_exists(DENY_LIST_FILE || BLACKLIST_FILE)
end
alias_method :deny_list, :blacklist
deprecate_method :blacklist, :deny_list

def whitelist
@whitelist ||= load_if_exists(WHITELIST_FILE)
@allow_list ||= load_if_exists(ALLOW_LIST_FILE || WHITELIST_FILE)
end
alias_method :allow_list, :whitelist
deprecate_method :whitelist, :allow_list

private

Expand Down
11 changes: 9 additions & 2 deletions lib/valid_email2/address.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
require "valid_email2"
require "resolv"
require "mail"
require_relative "../helpers/deprecation_helper"

module ValidEmail2
class Address
extend DeprecationHelper

attr_accessor :address

PROHIBITED_DOMAIN_CHARACTERS_REGEX = /[+!_\/\s'`]/
Expand Down Expand Up @@ -85,12 +88,16 @@ def disposable_mx_server?
end

def whitelisted?
domain_is_in?(ValidEmail2.whitelist)
domain_is_in?(ValidEmail2.allow_list)
end
alias_method :allow_listed?, :whitelisted?
deprecate_method :whitelisted?, :allow_listed?

def blacklisted?
valid? && domain_is_in?(ValidEmail2.blacklist)
valid? && domain_is_in?(ValidEmail2.deny_list)
end
alias_method :deny_listed?, :blacklisted?
deprecate_method :blacklisted?, :deny_listed?

def valid_mx?
return false unless valid?
Expand Down
21 changes: 18 additions & 3 deletions lib/valid_email2/email_validator.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
require "valid_email2/address"
require "active_model"
require "active_model/validations"
require_relative "../helpers/deprecation_helper"

module ValidEmail2
class EmailValidator < ActiveModel::EachValidator
include DeprecationHelper

def default_options
{ disposable: false, mx: false, strict_mx: false, disallow_subaddressing: false, multiple: false, dns_timeout: 5, dns_nameserver: nil }
end
Expand Down Expand Up @@ -33,15 +36,27 @@ def validate_each(record, attribute, value)
end

if options[:disposable_with_whitelist]
error(record, attribute) && return if addresses.any? { |address| address.disposable? && !address.whitelisted? }
deprecation_message(:disposable_with_whitelist, :disposable_with_allow_list)
end

if options[:disposable_with_allow_list] || options[:disposable_with_whitelist]
error(record, attribute) && return if addresses.any? { |address| address.disposable? && !address.allow_listed? }
end

if options[:disposable_domain_with_whitelist]
error(record, attribute) && return if addresses.any? { |address| address.disposable_domain? && !address.whitelisted? }
deprecation_message(:disposable_domain_with_whitelist, :disposable_domain_with_allow_list)
end

if options[:disposable_domain_with_allow_list] || options[:disposable_domain_with_whitelist]
error(record, attribute) && return if addresses.any? { |address| address.disposable_domain? && !address.allow_listed? }
end

if options[:blacklist]
error(record, attribute) && return if addresses.any?(&:blacklisted?)
deprecation_message(:blacklist, :deny_list)
end

if options[:deny_list] || options[:blacklist]
error(record, attribute) && return if addresses.any?(&:deny_listed?)
end

if options[:mx]
Expand Down
64 changes: 32 additions & 32 deletions spec/valid_email2_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,16 @@ class TestUserDisallowDisposableDomain < TestModel
validates :email, 'valid_email_2/email': { disposable_domain: true }
end

class TestUserDisallowDisposableWithWhitelist < TestModel
validates :email, 'valid_email_2/email': { disposable_with_whitelist: true }
class TestUserDisallowDisposableWithAllowList < TestModel
validates :email, 'valid_email_2/email': { disposable_with_allow_list: true }
end

class TestUserDisallowDisposableDomainWithWhitelist < TestModel
validates :email, 'valid_email_2/email': { disposable_domain_with_whitelist: true }
class TestUserDisallowDisposableDomainWithAllowList < TestModel
validates :email, 'valid_email_2/email': { disposable_domain_with_allow_list: true }
end

class TestUserDisallowBlacklisted < TestModel
validates :email, 'valid_email_2/email': { blacklist: true }
class TestUserDisallowDenyListed < TestModel
validates :email, 'valid_email_2/email': { deny_list: true }
end

class TestUserMessage < TestModel
Expand Down Expand Up @@ -208,58 +208,58 @@ class TestUserMultiple < TestModel
end
end

describe "with whitelisted emails" do
let(:whitelist_domain) { disposable_domain }
let(:whitelist_file_path) { "config/whitelisted_email_domains.yml" }
describe "with allow-listed emails" do
let(:allow_list_domain) { disposable_domain }
let(:allow_list_file_path) { "config/allow_listed_email_domains.yml" }

# Some of the specs below need to explictly set the whitelist var or it
# Some of the specs below need to explictly set the allow list var or it
# may be cached to an empty set
def set_whitelist
def set_allow_list
ValidEmail2.instance_variable_set(
:@whitelist,
ValidEmail2.send(:load_if_exists, ValidEmail2::WHITELIST_FILE)
:@allow_list,
ValidEmail2.send(:load_if_exists, ValidEmail2::ALLOW_LIST_FILE)
)
end

after do
FileUtils.rm(whitelist_file_path, force: true)
set_whitelist
FileUtils.rm(allow_list_file_path, force: true)
set_allow_list
end

it "is invalid if the domain is disposable and not in the whitelist" do
user = TestUserDisallowDisposableWithWhitelist.new(email: "foo@#{whitelist_domain}")
it "is invalid if the domain is disposable and not in the allow list" do
user = TestUserDisallowDisposableWithAllowList.new(email: "foo@#{allow_list_domain}")
expect(user.valid?).to be_falsey
end

it "is valid if the domain is disposable but in the whitelist" do
File.open(whitelist_file_path, "w") { |f| f.write [whitelist_domain].to_yaml }
set_whitelist
user = TestUserDisallowDisposableWithWhitelist.new(email: "foo@#{whitelist_domain}")
it "is valid if the domain is disposable but in the allow list" do
File.open(allow_list_file_path, "w") { |f| f.write [allow_list_domain].to_yaml }
set_allow_list
user = TestUserDisallowDisposableWithAllowList.new(email: "foo@#{allow_list_domain}")
expect(user.valid?).to be_truthy
end

it "is invalid if the domain is a disposable_domain and not in the whitelist" do
user = TestUserDisallowDisposableDomainWithWhitelist.new(email: "foo@#{whitelist_domain}")
it "is invalid if the domain is a disposable_domain and not in the allow list" do
user = TestUserDisallowDisposableDomainWithAllowList.new(email: "foo@#{allow_list_domain}")
expect(user.valid?).to be_falsey
end

it "is valid if the domain is a disposable_domain but in the whitelist" do
File.open(whitelist_file_path, "w") { |f| f.write [whitelist_domain].to_yaml }
set_whitelist
user = TestUserDisallowDisposableDomainWithWhitelist.new(email: "foo@#{whitelist_domain}")
it "is valid if the domain is a disposable_domain but in the allow list" do
File.open(allow_list_file_path, "w") { |f| f.write [allow_list_domain].to_yaml }
set_allow_list
user = TestUserDisallowDisposableDomainWithAllowList.new(email: "foo@#{allow_list_domain}")
expect(user.valid?).to be_truthy
end
end
end

describe "with blacklist validation" do
it "is valid if the domain is not blacklisted" do
user = TestUserDisallowBlacklisted.new(email: "[email protected]")
describe "with deny list validation" do
it "is valid if the domain is not deny-listed" do
user = TestUserDisallowDenyListed.new(email: "[email protected]")
expect(user.valid?).to be_truthy
end

it "is invalid if the domain is blacklisted" do
user = TestUserDisallowBlacklisted.new(email: "foo@blacklisted-test.com")
it "is invalid if the domain is deny-listed" do
user = TestUserDisallowDenyListed.new(email: "foo@deny-listed-test.com")
expect(user.valid?).to be_falsey
end
end
Expand Down
4 changes: 2 additions & 2 deletions valid_email2.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
spec.version = ValidEmail2::VERSION
spec.authors = ["Micke Lisinge"]
spec.email = ["[email protected]"]
spec.description = %q{ActiveModel validation for email. Including MX lookup and disposable email blacklist}
spec.summary = %q{ActiveModel validation for email. Including MX lookup and disposable email blacklist}
spec.description = %q{ActiveModel validation for email. Including MX lookup and disposable email deny list}
spec.summary = %q{ActiveModel validation for email. Including MX lookup and disposable email deny list}
spec.homepage = "https://github.com/micke/valid_email2"
spec.license = "MIT"

Expand Down

0 comments on commit 2782fe5

Please sign in to comment.