mirror of
https://github.com/meineerde/redmine.git
synced 2025-12-19 15:01:14 +00:00
Allowed/Disallowed email domains settings to restrict users' email addresses (#3369).
Patch by Yuichi HARADA and Go MAEDA. git-svn-id: http://svn.redmine.org/redmine/trunk@19735 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
d94226dd4c
commit
94c62816a5
@ -36,6 +36,7 @@ class EmailAddress < ActiveRecord::Base
|
|||||||
validates_length_of :address, :maximum => User::MAIL_LENGTH_LIMIT, :allow_nil => true
|
validates_length_of :address, :maximum => User::MAIL_LENGTH_LIMIT, :allow_nil => true
|
||||||
validates_uniqueness_of :address, :case_sensitive => false,
|
validates_uniqueness_of :address, :case_sensitive => false,
|
||||||
:if => Proc.new {|email| email.address_changed? && email.address.present?}
|
:if => Proc.new {|email| email.address_changed? && email.address.present?}
|
||||||
|
validate :validate_email_domain, :if => proc {|email| email.address.present?}
|
||||||
|
|
||||||
safe_attributes 'address'
|
safe_attributes 'address'
|
||||||
|
|
||||||
@ -51,6 +52,28 @@ class EmailAddress < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns true if the email domain is allowed regarding allowed/denied
|
||||||
|
# domains defined in application settings, otherwise false
|
||||||
|
def self.valid_domain?(domain_or_email)
|
||||||
|
denied, allowed =
|
||||||
|
[:email_domains_denied, :email_domains_allowed].map do |setting|
|
||||||
|
Setting.__send__(setting)
|
||||||
|
end
|
||||||
|
domain = domain_or_email.split('@').last
|
||||||
|
return false if denied.present? && domain_in?(domain, denied)
|
||||||
|
return false if allowed.present? && !domain_in?(domain, allowed)
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns true if domain belongs to domains list.
|
||||||
|
def self.domain_in?(domain, domains)
|
||||||
|
domain = domain.downcase
|
||||||
|
domains = domains.to_s.split(/[\s,]+/) unless domains.is_a?(Array)
|
||||||
|
domains.reject(&:blank?).map(&:downcase).any? do |s|
|
||||||
|
s.start_with?('.') ? domain.end_with?(s) : domain == s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# send a security notification to user that a new email address was added
|
# send a security notification to user that a new email address was added
|
||||||
@ -117,4 +140,8 @@ class EmailAddress < ActiveRecord::Base
|
|||||||
Token.where(:user_id => user_id, :action => tokens).delete_all
|
Token.where(:user_id => user_id, :action => tokens).delete_all
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def validate_email_domain
|
||||||
|
errors.add(:address, :invalid) unless self.class.valid_domain?(address)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -3,6 +3,12 @@
|
|||||||
<div class="box tabular settings">
|
<div class="box tabular settings">
|
||||||
<p><%= setting_text_field :max_additional_emails, :size => 6 %></p>
|
<p><%= setting_text_field :max_additional_emails, :size => 6 %></p>
|
||||||
|
|
||||||
|
<p><%= setting_text_area :email_domains_allowed %>
|
||||||
|
<em class="info"><%= l(:text_comma_separated) %> <%= l(:label_example) %>: example.com, example.org</em></p>
|
||||||
|
|
||||||
|
<p><%= setting_text_area :email_domains_denied %>
|
||||||
|
<em class="info"><%= l(:text_comma_separated) %> <%= l(:label_example) %>: .example.com, foo.example.org, example.net</em></p>
|
||||||
|
|
||||||
<p><%= setting_check_box :unsubscribe %></p>
|
<p><%= setting_check_box :unsubscribe %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -479,6 +479,8 @@ en:
|
|||||||
setting_force_default_language_for_loggedin: Force default language for logged-in users
|
setting_force_default_language_for_loggedin: Force default language for logged-in users
|
||||||
setting_link_copied_issue: Link issues on copy
|
setting_link_copied_issue: Link issues on copy
|
||||||
setting_max_additional_emails: Maximum number of additional email addresses
|
setting_max_additional_emails: Maximum number of additional email addresses
|
||||||
|
setting_email_domains_allowed: Allowed email domains
|
||||||
|
setting_email_domains_denied: Disallowed email domains
|
||||||
setting_search_results_per_page: Search results per page
|
setting_search_results_per_page: Search results per page
|
||||||
setting_attachment_extensions_allowed: Allowed extensions
|
setting_attachment_extensions_allowed: Allowed extensions
|
||||||
setting_attachment_extensions_denied: Disallowed extensions
|
setting_attachment_extensions_denied: Disallowed extensions
|
||||||
|
|||||||
@ -53,6 +53,10 @@ password_max_age:
|
|||||||
max_additional_emails:
|
max_additional_emails:
|
||||||
format: int
|
format: int
|
||||||
default: 5
|
default: 5
|
||||||
|
email_domains_allowed:
|
||||||
|
default:
|
||||||
|
email_domains_denied:
|
||||||
|
default:
|
||||||
# Maximum lifetime of user sessions in minutes
|
# Maximum lifetime of user sessions in minutes
|
||||||
session_lifetime:
|
session_lifetime:
|
||||||
format: int
|
format: int
|
||||||
|
|||||||
@ -118,6 +118,36 @@ class EmailAddressesControllerTest < Redmine::ControllerTest
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_create_with_disallowed_domain_should_fail
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
|
||||||
|
with_settings :email_domains_denied => 'black.example' do
|
||||||
|
assert_no_difference 'EmailAddress.count' do
|
||||||
|
post :create, :params => {
|
||||||
|
:user_id => 2,
|
||||||
|
:email_address => {
|
||||||
|
:address => 'another@black.example'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_response :success
|
||||||
|
assert_select_error 'Email is invalid'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
with_settings :email_domains_allowed => 'white.example' do
|
||||||
|
assert_no_difference 'EmailAddress.count' do
|
||||||
|
post :create, :params => {
|
||||||
|
:user_id => 2,
|
||||||
|
:email_address => {
|
||||||
|
:address => 'something@example.fr'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_response :success
|
||||||
|
assert_select_error 'Email is invalid'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_create_should_send_security_notification
|
def test_create_should_send_security_notification
|
||||||
@request.session[:user_id] = 2
|
@request.session[:user_id] = 2
|
||||||
ActionMailer::Base.deliveries.clear
|
ActionMailer::Base.deliveries.clear
|
||||||
|
|||||||
@ -30,4 +30,38 @@ class EmailAddressTest < ActiveSupport::TestCase
|
|||||||
email = EmailAddress.new(address: 'jsmith@example.xn--80akhbyknj4f')
|
email = EmailAddress.new(address: 'jsmith@example.xn--80akhbyknj4f')
|
||||||
assert email.valid?
|
assert email.valid?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_address_should_be_validated_against_denied_domains
|
||||||
|
with_settings :email_domains_denied => "black.test\r\nBLACK.EXAMPLE, .subdomain.test" do
|
||||||
|
email = EmailAddress.new(address: 'user@black.test')
|
||||||
|
assert_not email.valid?
|
||||||
|
email = EmailAddress.new(address: 'user@notblack.test')
|
||||||
|
assert email.valid?
|
||||||
|
email = EmailAddress.new(address: 'user@BLACK.TEST')
|
||||||
|
assert_not email.valid?
|
||||||
|
email = EmailAddress.new(address: 'user@black.example')
|
||||||
|
assert_not email.valid?
|
||||||
|
email = EmailAddress.new(address: 'user@subdomain.test')
|
||||||
|
assert email.valid?
|
||||||
|
email = EmailAddress.new(address: 'user@foo.subdomain.test')
|
||||||
|
assert_not email.valid?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_address_should_be_validated_against_allowed_domains
|
||||||
|
with_settings :email_domains_allowed => "white.test\r\nWHITE.EXAMPLE, .subdomain.test" do
|
||||||
|
email = EmailAddress.new(address: 'user@white.test')
|
||||||
|
assert email.valid?
|
||||||
|
email = EmailAddress.new(address: 'user@notwhite.test')
|
||||||
|
assert_not email.valid?
|
||||||
|
email = EmailAddress.new(address: 'user@WHITE.TEST')
|
||||||
|
assert email.valid?
|
||||||
|
email = EmailAddress.new(address: 'user@white.example')
|
||||||
|
assert email.valid?
|
||||||
|
email = EmailAddress.new(address: 'user@subdomain.test')
|
||||||
|
assert_not email.valid?
|
||||||
|
email = EmailAddress.new(address: 'user@foo.subdomain.test')
|
||||||
|
assert email.valid?
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user