-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add in ability to dynamically load in blacklisted domains
- Loading branch information
Showing
5 changed files
with
180 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# frozen_string_literal:true | ||
|
||
module ValidEmail2 | ||
class DynamicOptionValues | ||
class << self | ||
def blacklist | ||
@blacklist ||= Set.new | ||
end | ||
|
||
def blacklist=(set) | ||
return unless set.is_a?(Set) | ||
|
||
@blacklist = set | ||
end | ||
|
||
def blacklist_active_record_query | ||
@blacklist_active_record_query ||= default_active_record_query | ||
end | ||
|
||
def blacklist_active_record_query=(query_hash) | ||
return unless valid_query_hash?(query_hash) | ||
|
||
@blacklist_active_record_query = query_hash | ||
end | ||
|
||
def parse_option_for_additional_items(type, value) | ||
return false unless respond_to?("#{type}=") | ||
|
||
case value | ||
when NilClass | ||
return false | ||
when TrueClass, FalseClass | ||
return value | ||
when Set | ||
send("#{type}=", value) | ||
when Array | ||
send("#{type}=", Set.new(value)) | ||
when Proc | ||
result_value = value.call | ||
return parse_option_for_additional_items(type, result_value) | ||
when Hash, HashWithIndifferentAccess | ||
return false unless valid_query_hash?(value) | ||
return false unless respond_to?("#{type}_active_record_query=") | ||
|
||
send("#{type}_active_record_query=", value) | ||
else | ||
return false | ||
end | ||
|
||
true | ||
end | ||
|
||
def domain_is_in?(type, address) | ||
return false unless type.is_a?(Symbol) | ||
return false unless respond_to?(type) | ||
return false unless address.is_a?(Mail::Address) | ||
|
||
downcase_domain = address.domain.downcase | ||
type_result = send(type).include?(downcase_domain) | ||
return type_result if type_result | ||
|
||
return false unless respond_to?("#{type}_active_record_query") | ||
|
||
option_hash = send("#{type}_active_record_query") | ||
return false unless valid_query_hash?(option_hash) | ||
|
||
scope = option_hash[:active_record_scope] | ||
attribute = option_hash[:attribute] | ||
scope.exists?(attribute => downcase_domain) | ||
end | ||
|
||
private | ||
|
||
def valid_query_hash?(query_hash) | ||
valid_class_array = [Hash] | ||
valid_class_array << HashWithIndifferentAccess if defined?(HashWithIndifferentAccess) | ||
return false unless valid_class_array.include?(query_hash.class) | ||
|
||
scope = query_hash[:active_record_scope] | ||
unless scope.is_a?(Class) && | ||
scope.respond_to?(:where) && | ||
scope.respond_to?(:exists?) && | ||
scope.respond_to?(:column_names) | ||
return false | ||
end | ||
|
||
attribute = query_hash[:attribute] | ||
return false unless attribute.is_a?(Symbol) && scope.column_names.include?(attribute.to_s) | ||
|
||
true | ||
end | ||
|
||
def default_active_record_query | ||
@default_active_record_query ||= { active_record_scope: nil, attribute: nil } | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,6 +59,22 @@ class TestUserDisallowDenyListed < TestModel | |
validates :email, 'valid_email_2/email': { deny_list: true } | ||
end | ||
|
||
class TestUserDisallowBlacklistedWithDynamicArray < TestModel | ||
validates :email, 'valid_email_2/email': { blacklist: ["test-dynamic-array.com"] } | ||
end | ||
|
||
class TestUserDisallowBlacklistedWithDynamicSet < TestModel | ||
validates :email, 'valid_email_2/email': { blacklist: Set.new(["test-dynamic-set.com"]) } | ||
end | ||
|
||
class TestUserDisallowBlacklistedWithDynamicProc < TestModel | ||
validates :email, 'valid_email_2/email': { blacklist: proc { ["test-dynamic-proc.com"] } } | ||
end | ||
|
||
class TestUserDisallowBlacklistedWithDynamicHash < TestModel | ||
validates :email, 'valid_email_2/email': { blacklist: { active_record_scope: TestDynamicDomainModel, attribute: :domain } } | ||
end | ||
|
||
class TestUserMessage < TestModel | ||
validates :email, 'valid_email_2/email': { message: "custom message" } | ||
end | ||
|
@@ -262,6 +278,34 @@ def set_allow_list | |
user = TestUserDisallowDenyListed.new(email: "[email protected]") | ||
expect(user.valid?).to be_falsey | ||
end | ||
|
||
it "is invalid if the domain is blacklisted via a dynamic array option" do | ||
user = TestUserDisallowBlacklistedWithDynamicArray.new(email: "[email protected]") | ||
expect(user.valid?).to be_falsy | ||
end | ||
|
||
it "is invalid if the domain is blacklisted via a dynamic set option" do | ||
user = TestUserDisallowBlacklistedWithDynamicSet.new(email: "[email protected]") | ||
expect(user.valid?).to be_falsy | ||
end | ||
|
||
it "is invalid if the domain is blacklisted via a dynamic proc option" do | ||
user = TestUserDisallowBlacklistedWithDynamicProc.new(email: "[email protected]") | ||
expect(user.valid?).to be_falsy | ||
end | ||
|
||
it "is invalid if the domain is blacklisted via a dynamic hash option" do | ||
invalid_dynamic_domain = "test-dynamic-hash.com" | ||
TestDynamicDomainModel.domain_attribute_values = [invalid_dynamic_domain] | ||
user = TestUserDisallowBlacklistedWithDynamicHash.new(email: "foo@#{invalid_dynamic_domain}") | ||
expect(user.valid?).to be_falsy | ||
end | ||
|
||
it "is valid if the dynamic domain list does not include the email domain" do | ||
TestDynamicDomainModel.domain_attribute_values = ["not-blacklisted.com"] | ||
user = TestUserDisallowBlacklistedWithDynamicHash.new(email: "[email protected]") | ||
expect(user.valid?).to be_truthy | ||
end | ||
end | ||
|
||
describe "with mx validation" do | ||
|