Compare commits

...

4 Commits

Author SHA1 Message Date
Matt Jankowski
c2b5324931
Merge a8dfd353b2 into 74fc4dbacf 2025-07-15 17:05:57 +00:00
diondiondion
74fc4dbacf
refactor: Only remove pointer-events when necessary (#35390)
Some checks failed
Check i18n / check-i18n (push) Waiting to run
Chromatic / Run Chromatic (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (ruby) (push) Waiting to run
Check formatting / lint (push) Waiting to run
CSS Linting / lint (push) Waiting to run
Ruby Testing / build (production) (push) Waiting to run
Ruby Testing / build (test) (push) Waiting to run
Ruby Testing / test (.ruby-version) (push) Blocked by required conditions
Ruby Testing / test (3.2) (push) Blocked by required conditions
Ruby Testing / test (3.3) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (.ruby-version) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (3.2) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (3.3) (push) Blocked by required conditions
Ruby Testing / End to End testing (.ruby-version) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.2) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.3) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:8.10.2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, opensearchproject/opensearch:2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.2, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.3, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Crowdin / Upload translations / upload-translations (push) Has been cancelled
Haml Linting / lint (push) Has been cancelled
Ruby Linting / lint (push) Has been cancelled
Historical data migration test / test (14-alpine) (push) Has been cancelled
Historical data migration test / test (15-alpine) (push) Has been cancelled
Historical data migration test / test (16-alpine) (push) Has been cancelled
Historical data migration test / test (17-alpine) (push) Has been cancelled
2025-07-15 15:57:31 +00:00
Matt Jankowski
a8dfd353b2 Use Regexp.escape on domain values 2025-07-03 18:29:27 -04:00
Matt Jankowski
a80763abbe Move allow/deny list config to email_domains area 2025-07-03 18:29:27 -04:00
10 changed files with 69 additions and 31 deletions

View File

@ -2848,7 +2848,6 @@ a.account__display-name {
&__pane {
height: 100%;
overflow: hidden;
pointer-events: none;
display: flex;
justify-content: flex-end;
min-width: 285px;
@ -2860,7 +2859,6 @@ a.account__display-name {
&__inner {
position: fixed;
width: 285px;
pointer-events: auto;
height: 100%;
}
}

View File

@ -34,9 +34,13 @@ class EmailMxValidator < ActiveModel::Validator
end
def on_allowlist?(domain)
return false if Rails.configuration.x.email_domains_allowlist.blank?
return false if allowed_email_domains.blank?
Rails.configuration.x.email_domains_allowlist.include?(domain)
allowed_email_domains.include?(domain)
end
def allowed_email_domains
Rails.configuration.x.email_domains.allowlist
end
def resolve_mx(domain)

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true
class UserEmailValidator < ActiveModel::Validator
SEPARATOR = '|'
def validate(user)
return if user.valid_invitation? || user.email.blank?
@ -23,20 +25,42 @@ class UserEmailValidator < ActiveModel::Validator
end
def not_allowed_through_configuration?(email)
return false if Rails.configuration.x.email_domains_allowlist.blank?
return false if allowed_email_domains.blank?
domains = Rails.configuration.x.email_domains_allowlist.gsub('.', '\.')
regexp = Regexp.new("@(.+\\.)?(#{domains})$", true)
domains = escaped_domains(allowed_email_domains)
email !~ regexp
email !~ allowed_domain_pattern(domains)
end
def disallowed_through_configuration?(email)
return false if Rails.configuration.x.email_domains_denylist.blank?
return false if denied_email_domains.blank?
domains = Rails.configuration.x.email_domains_denylist.gsub('.', '\.')
regexp = Regexp.new("@(.+\\.)?(#{domains})", true)
domains = escaped_domains(denied_email_domains)
regexp.match?(email)
denied_domain_pattern(domains).match?(email)
end
def allowed_domain_pattern(domains)
Regexp.new("@(.+\\.)?(#{domains})$", true)
end
def denied_domain_pattern(domains)
Regexp.new("@(.+\\.)?(#{domains})", true)
end
def escaped_domains(domains)
domains
.split(SEPARATOR)
.map { |domain| Regexp.escape(domain) }
.join(SEPARATOR)
.to_s
end
def allowed_email_domains
Rails.configuration.x.email_domains.allowlist
end
def denied_email_domains
Rails.configuration.x.email_domains.denylist
end
end

View File

@ -11,7 +11,7 @@ class Scheduler::AutoCloseRegistrationsScheduler
OPEN_REGISTRATIONS_MODERATOR_THRESHOLD = 1.week + UserTrackingConcern::SIGN_IN_UPDATE_FREQUENCY
def perform
return if Rails.configuration.x.email_domains_allowlist.present? || ENV['DISABLE_AUTOMATIC_SWITCHING_TO_APPROVED_REGISTRATIONS'] == 'true'
return if Rails.configuration.x.email_domains.allowlist.present? || ENV['DISABLE_AUTOMATIC_SWITCHING_TO_APPROVED_REGISTRATIONS'] == 'true'
return unless Setting.registrations_mode == 'open'
switch_to_approval_mode! unless active_moderators?

View File

@ -106,6 +106,7 @@ module Mastodon
config.x.cache_buster = config_for(:cache_buster)
config.x.captcha = config_for(:captcha)
config.x.email = config_for(:email)
config.x.email_domains = config_for(:email_domains)
config.x.mastodon = config_for(:mastodon)
config.x.omniauth = config_for(:omniauth)
config.x.translation = config_for(:translation)

3
config/email_domains.yml Normal file
View File

@ -0,0 +1,3 @@
shared:
denylist: <%= ENV.fetch('EMAIL_DOMAIN_DENYLIST', nil) || ENV.fetch('EMAIL_DOMAIN_BLACKLIST', '') %>
allowlist: <%= ENV.fetch('EMAIL_DOMAIN_ALLOWLIST', nil) || ENV.fetch('EMAIL_DOMAIN_WHITELIST', '') %>

View File

@ -29,3 +29,17 @@ if ENV.key?('WHITELIST_MODE')
LIMITED_FEDERATION_MODE. Please update your configuration.
MESSAGE
end
if ENV.key?('EMAIL_DOMAIN_BLACKLIST')
warn(<<~MESSAGE.squish)
WARNING: The environment variable EMAIL_DOMAIN_BLACKLIST has been replaced
with EMAIL_DOMAIN_DENYLIST. Please update your configuration.
MESSAGE
end
if ENV.key?('EMAIL_DOMAIN_WHITELIST')
warn(<<~MESSAGE.squish)
WARNING: The environment variable EMAIL_DOMAIN_WHITELIST has been replaced
with EMAIL_DOMAIN_ALLOWLIST. Please update your configuration.
MESSAGE
end

View File

@ -1,6 +0,0 @@
# frozen_string_literal: true
Rails.application.configure do
config.x.email_domains_denylist = ENV.fetch('EMAIL_DOMAIN_DENYLIST', nil) || ENV.fetch('EMAIL_DOMAIN_BLACKLIST', '')
config.x.email_domains_allowlist = ENV.fetch('EMAIL_DOMAIN_ALLOWLIST', nil) || ENV.fetch('EMAIL_DOMAIN_WHITELIST', '')
end

View File

@ -139,13 +139,13 @@ RSpec.describe User do
describe 'email domains denylist integration' do
around do |example|
original = Rails.configuration.x.email_domains_denylist
original = Rails.configuration.x.email_domains.denylist
Rails.configuration.x.email_domains_denylist = 'mvrht.com'
Rails.configuration.x.email_domains.denylist = 'mvrht.com'
example.run
Rails.configuration.x.email_domains_denylist = original
Rails.configuration.x.email_domains.denylist = original
end
it 'allows a user with an email domain that is not on the denylist to be created' do
@ -392,13 +392,13 @@ RSpec.describe User do
describe 'allowlist integration' do
around do |example|
original = Rails.configuration.x.email_domains_allowlist
original = Rails.configuration.x.email_domains.allowlist
Rails.configuration.x.email_domains_allowlist = 'mastodon.space'
Rails.configuration.x.email_domains.allowlist = 'mastodon.space'
example.run
Rails.configuration.x.email_domains_allowlist = original
Rails.configuration.x.email_domains.allowlist = original
end
it 'does not allow a user to be created when their email is not on the allowlist' do
@ -418,13 +418,13 @@ RSpec.describe User do
context 'with a subdomain on the denylist' do
around do |example|
original = Rails.configuration.x.email_domains_denylist
original = Rails.configuration.x.email_domains.denylist
example.run
Rails.configuration.x.email_domains_denylist = original
Rails.configuration.x.email_domains.denylist = original
end
it 'does not allow a user to be created with an email subdomain on the denylist even if the top domain is on the allowlist' do
Rails.configuration.x.email_domains_denylist = 'denylisted.mastodon.space'
Rails.configuration.x.email_domains.denylist = 'denylisted.mastodon.space'
user = described_class.new(email: 'foo@denylisted.mastodon.space', account: account, password: password)
expect(user).to_not be_valid

View File

@ -9,10 +9,10 @@ RSpec.describe EmailMxValidator do
context 'with an e-mail domain that is explicitly allowed' do
around do |block|
tmp = Rails.configuration.x.email_domains_allowlist
Rails.configuration.x.email_domains_allowlist = 'example.com'
tmp = Rails.configuration.x.email_domains.allowlist
Rails.configuration.x.email_domains.allowlist = 'example.com'
block.call
Rails.configuration.x.email_domains_allowlist = tmp
Rails.configuration.x.email_domains.allowlist = tmp
end
it 'does not add errors if there are no DNS records' do