about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.env.production.sample2
-rw-r--r--app/lib/email_validator.rb17
-rw-r--r--config/initializers/blacklists.rb1
-rw-r--r--spec/models/user_spec.rb37
4 files changed, 55 insertions, 2 deletions
diff --git a/.env.production.sample b/.env.production.sample
index bd81b8fca..a7f9eb4bf 100644
--- a/.env.production.sample
+++ b/.env.production.sample
@@ -22,6 +22,8 @@ OTP_SECRET=
 # SINGLE_USER_MODE=true
 # Prevent registrations with following e-mail domains
 # EMAIL_DOMAIN_BLACKLIST=example1.com|example2.de|etc
+# Only allow registrations with the following e-mail domains
+# EMAIL_DOMAIN_WHITELIST=example1.com|example2.de|etc
 
 # E-mail configuration
 SMTP_SERVER=smtp.mailgun.org
diff --git a/app/lib/email_validator.rb b/app/lib/email_validator.rb
index 856b8b1f7..06e9375f6 100644
--- a/app/lib/email_validator.rb
+++ b/app/lib/email_validator.rb
@@ -2,17 +2,30 @@
 
 class EmailValidator < ActiveModel::EachValidator
   def validate_each(record, attribute, value)
-    return if Rails.configuration.x.email_domains_blacklist.empty?
-
     record.errors.add(attribute, I18n.t('users.invalid_email')) if blocked_email?(value)
   end
 
   private
 
   def blocked_email?(value)
+    on_blacklist?(value) || not_on_whitelist?(value)
+  end
+
+  def on_blacklist?(value)
+    return false if Rails.configuration.x.email_domains_blacklist.blank?
+
     domains = Rails.configuration.x.email_domains_blacklist.gsub('.', '\.')
     regexp  = Regexp.new("@(.+\\.)?(#{domains})", true)
 
     value =~ regexp
   end
+
+  def not_on_whitelist?(value)
+    return false if Rails.configuration.x.email_domains_whitelist.blank?
+
+    domains = Rails.configuration.x.email_domains_whitelist.gsub('.', '\.')
+    regexp  = Regexp.new("@(.+\\.)?(#{domains})", true)
+
+    value !~ regexp
+  end
 end
diff --git a/config/initializers/blacklists.rb b/config/initializers/blacklists.rb
index 52646e64d..6db7be7dc 100644
--- a/config/initializers/blacklists.rb
+++ b/config/initializers/blacklists.rb
@@ -2,4 +2,5 @@
 
 Rails.application.configure do
   config.x.email_domains_blacklist = ENV.fetch('EMAIL_DOMAIN_BLACKLIST') { 'mvrht.com' }
+  config.x.email_domains_whitelist = ENV.fetch('EMAIL_DOMAIN_WHITELIST') { '' }  
 end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 64de06749..aa777fd39 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1,5 +1,42 @@
 require 'rails_helper'
 
 RSpec.describe User, type: :model do
+  let(:account) { Fabricate(:account, username: 'alice') }  
+  let(:password) { 'abcd1234' }
 
+  describe 'blacklist' do
+    it 'should allow a non-blacklisted user to be created' do
+      user = User.new(email: 'foo@example.com', account: account, password: password)
+
+      expect(user.valid?).to be_truthy
+    end
+    
+    it 'should not allow a blacklisted user to be created' do
+      user = User.new(email: 'foo@mvrht.com', account: account, password: password)
+
+      expect(user.valid?).to be_falsey
+    end
+  end
+
+  describe 'whitelist' do
+    around(:each) do |example|
+      old_whitelist = Rails.configuration.x.email_whitelist
+
+      Rails.configuration.x.email_domains_whitelist = 'mastodon.space'
+
+      example.run
+
+      Rails.configuration.x.email_domains_whitelist = old_whitelist
+    end
+
+    it 'should not allow a user to be created unless they are whitelisted' do
+      user = User.new(email: 'foo@example.com', account: account, password: password)
+      expect(user.valid?).to be_falsey
+    end
+
+    it 'should allow a user to be created if they are whitelisted' do
+      user = User.new(email: 'foo@mastodon.space', account: account, password: password)
+      expect(user.valid?).to be_truthy
+    end    
+  end
 end