From 77e3434d81f79883556cf82eba59d1fec083283e Mon Sep 17 00:00:00 2001 From: Sam Bauch Date: Mon, 18 Mar 2013 15:48:56 -0400 Subject: [PATCH] added email whitelist SiteSetting feature to replicate email blacklist. email_validator method now also uses the regex method for both the whitelist and blacklist. --- app/models/site_setting.rb | 1 + app/models/user.rb | 16 +++++++++++---- config/locales/server.en.yml | 1 + spec/models/user_spec.rb | 39 +++++++++++++++++++++++++++++++++++- 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb index 38a860679a7..7658f66f468 100644 --- a/app/models/site_setting.rb +++ b/app/models/site_setting.rb @@ -33,6 +33,7 @@ class SiteSetting < ActiveRecord::Base client_setting(:flush_timings_secs, 5) client_setting(:supress_reply_directly_below, true) client_setting(:email_domains_blacklist, 'mailinator.com') + client_setting(:email_domains_whitelist) client_setting(:version_checks, true) client_setting(:min_title_similar_length, 10) client_setting(:min_body_similar_length, 15) diff --git a/app/models/user.rb b/app/models/user.rb index b8c69b23500..ed0e0cda810 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -532,14 +532,22 @@ class User < ActiveRecord::Base end def email_validator - if (setting = SiteSetting.email_domains_blacklist).present? - domains = setting.gsub('.', '\.') - regexp = Regexp.new("@(#{domains})", true) - if self.email =~ regexp + if (setting = SiteSetting.email_domains_whitelist).present? + unless email_in_restriction_setting?(setting) + errors.add(:email, I18n.t(:'user.email.not_allowed')) + end + elsif (setting = SiteSetting.email_domains_blacklist).present? + if email_in_restriction_setting?(setting) errors.add(:email, I18n.t(:'user.email.not_allowed')) end end end + + def email_in_restriction_setting?(setting) + domains = setting.gsub('.', '\.') + regexp = Regexp.new("@(#{domains})", true) + self.email =~ regexp + end def password_validator if (@raw_password && @raw_password.length < 6) || (@password_required && !@raw_password) diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 8124f6796ae..1e8301f57b6 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -356,6 +356,7 @@ en: supress_reply_directly_below: "Don't show reply count on a post when there is a single reply directly below" allow_index_in_robots_txt: "Site should be indexed by search engines (update robots.txt)" email_domains_blacklist: "A pipe-delimited list of email domains that are not allowed. Example: mailinator.com|trashmail.net" + email_domains_whitelist: "A pipe-delimited list of email domains that users may register with. WARNING: Users with email domains other than those listed will not be allowed." version_checks: "Ping the Discourse Hub for version updates and show version messages on the /admin dashboard" port: "Use this HTTP port rather than the default of port 80. Leave blank for none, mainly useful for development" diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 9feff9f5df9..e6b5d2ee8ca 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -471,7 +471,12 @@ describe User do Fabricate.build(:user, email: 'notgood@trashmail.net').should_not be_valid Fabricate.build(:user, email: 'mailinator.com@gmail.com').should be_valid end - + + it 'should not reject partial matches' do + SiteSetting.stubs(:email_domains_blacklist).returns('mail.com') + Fabricate.build(:user, email: 'mailinator@gmail.com').should be_valid + end + it 'should reject some emails based on the email_domains_blacklist site setting ignoring case' do SiteSetting.stubs(:email_domains_blacklist).returns('trashmail.net') Fabricate.build(:user, email: 'notgood@TRASHMAIL.NET').should_not be_valid @@ -494,6 +499,38 @@ describe User do u.email = 'nope@mailinator.com' u.should_not be_valid end + + it 'whitelist should reject some emails based on the email_domains_whitelist site setting' do + SiteSetting.stubs(:email_domains_whitelist).returns('vaynermedia.com') + Fabricate.build(:user, email: 'notgood@mailinator.com').should_not be_valid + Fabricate.build(:user, email: 'sbauch@vaynermedia.com').should be_valid + end + + it 'should reject some emails based on the email_domains_whitelist site setting when whitelisting multiple domains' do + SiteSetting.stubs(:email_domains_whitelist).returns('vaynermedia.com|gmail.com') + Fabricate.build(:user, email: 'notgood@mailinator.com').should_not be_valid + Fabricate.build(:user, email: 'notgood@trashmail.net').should_not be_valid + Fabricate.build(:user, email: 'mailinator.com@gmail.com').should be_valid + Fabricate.build(:user, email: 'mailinator.com@vaynermedia.com').should be_valid + end + + it 'should accept some emails based on the email_domains_whitelist site setting ignoring case' do + SiteSetting.stubs(:email_domains_whitelist).returns('vaynermedia.com') + Fabricate.build(:user, email: 'good@VAYNERMEDIA.COM').should be_valid + end + + it 'email whitelist should not be used to validate existing records' do + u = Fabricate(:user, email: 'in_before_whitelisted@fakemail.com') + SiteSetting.stubs(:email_domains_blacklist).returns('vaynermedia.com') + u.should be_valid + end + + it 'email whitelist should be used when email is being changed' do + SiteSetting.stubs(:email_domains_whitelist).returns('vaynermedia.com') + u = Fabricate(:user, email: 'good@vaynermedia.com') + u.email = 'nope@mailinator.com' + u.should_not be_valid + end end describe 'passwords' do