summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorRobert Speicher <robert@gitlab.com>2016-07-20 20:26:00 +0000
committerRobert Speicher <robert@gitlab.com>2016-07-20 20:26:00 +0000
commit22c8e21bf432a68f05bd81685d76acc0a3c9607f (patch)
tree3d113695853db1348f31d1fbc1fbe17590aecefa /app
parent5a77eb153669bfbac4ab1f05615d11965beb826d (diff)
parent1a057d2b4013feb151e77aa71dd0b5a83412d2d6 (diff)
downloadgitlab-ce-22c8e21bf432a68f05bd81685d76acc0a3c9607f.tar.gz
Merge branch 'email-domain-blacklist' into 'master'
Added the ability to block sign ups using a domain blacklist. As part of this MR, I restructured the Application Settings form to separate **Sign up** related settings from **Sign in** related settings and make everything cleaner and easier to read. Fixes #19749 Related to #5573 See merge request !5259
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/admin.js.coffee11
-rw-r--r--app/controllers/admin/application_settings_controller.rb6
-rw-r--r--app/models/application_setting.rb52
-rw-r--r--app/models/user.rb61
-rw-r--r--app/views/admin/application_settings/_form.html.haml57
5 files changed, 135 insertions, 52 deletions
diff --git a/app/assets/javascripts/admin.js.coffee b/app/assets/javascripts/admin.js.coffee
index b2b8e1b7ffb..90c09619f8c 100644
--- a/app/assets/javascripts/admin.js.coffee
+++ b/app/assets/javascripts/admin.js.coffee
@@ -38,3 +38,14 @@ class @Admin
$('li.group_member').bind 'ajax:success', ->
Turbolinks.visit(location.href)
+
+ showBlacklistType = ->
+ if $("input[name='blacklist_type']:checked").val() == 'file'
+ $('.blacklist-file').show()
+ $('.blacklist-raw').hide()
+ else
+ $('.blacklist-file').hide()
+ $('.blacklist-raw').show()
+
+ $("input[name='blacklist_type']").click showBlacklistType
+ showBlacklistType()
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 23ba83aba0e..9e1dc15de84 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -64,6 +64,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
params[:application_setting][:disabled_oauth_sign_in_sources] =
AuthHelper.button_based_providers.map(&:to_s) -
Array(enabled_oauth_sign_in_sources)
+ params.delete(:domain_blacklist_raw) if params[:domain_blacklist_file]
params.require(:application_setting).permit(
:default_projects_limit,
@@ -83,7 +84,10 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:default_project_visibility,
:default_snippet_visibility,
:default_group_visibility,
- :restricted_signup_domains_raw,
+ :domain_whitelist_raw,
+ :domain_blacklist_enabled,
+ :domain_blacklist_raw,
+ :domain_blacklist_file,
:version_check_enabled,
:admin_notification_email,
:user_oauth_applications,
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index c6f77cc055f..8c19d9dc9c8 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -4,12 +4,20 @@ class ApplicationSetting < ActiveRecord::Base
add_authentication_token_field :health_check_access_token
CACHE_KEY = 'application_setting.last'
+ DOMAIN_LIST_SEPARATOR = %r{\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace
+ | # or
+ \s # any whitespace character
+ | # or
+ [\r\n] # any number of newline characters
+ }x
serialize :restricted_visibility_levels
serialize :import_sources
serialize :disabled_oauth_sign_in_sources, Array
- serialize :restricted_signup_domains, Array
- attr_accessor :restricted_signup_domains_raw
+ serialize :domain_whitelist, Array
+ serialize :domain_blacklist, Array
+
+ attr_accessor :domain_whitelist_raw, :domain_blacklist_raw
validates :session_expire_delay,
presence: true,
@@ -62,6 +70,10 @@ class ApplicationSetting < ActiveRecord::Base
validates :enabled_git_access_protocol,
inclusion: { in: %w(ssh http), allow_blank: true, allow_nil: true }
+ validates :domain_blacklist,
+ presence: { message: 'Domain blacklist cannot be empty if Blacklist is enabled.' },
+ if: :domain_blacklist_enabled?
+
validates_each :restricted_visibility_levels do |record, attr, value|
unless value.nil?
value.each do |level|
@@ -129,7 +141,7 @@ class ApplicationSetting < ActiveRecord::Base
session_expire_delay: Settings.gitlab['session_expire_delay'],
default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'],
- restricted_signup_domains: Settings.gitlab['restricted_signup_domains'],
+ domain_whitelist: Settings.gitlab['domain_whitelist'],
import_sources: %w[github bitbucket gitlab gitorious google_code fogbugz git gitlab_project],
shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'],
max_artifacts_size: Settings.artifacts['max_size'],
@@ -150,20 +162,30 @@ class ApplicationSetting < ActiveRecord::Base
ActiveRecord::Base.connection.column_exists?(:application_settings, :home_page_url)
end
- def restricted_signup_domains_raw
- self.restricted_signup_domains.join("\n") unless self.restricted_signup_domains.nil?
+ def domain_whitelist_raw
+ self.domain_whitelist.join("\n") unless self.domain_whitelist.nil?
+ end
+
+ def domain_blacklist_raw
+ self.domain_blacklist.join("\n") unless self.domain_blacklist.nil?
+ end
+
+ def domain_whitelist_raw=(values)
+ self.domain_whitelist = []
+ self.domain_whitelist = values.split(DOMAIN_LIST_SEPARATOR)
+ self.domain_whitelist.reject! { |d| d.empty? }
+ self.domain_whitelist
+ end
+
+ def domain_blacklist_raw=(values)
+ self.domain_blacklist = []
+ self.domain_blacklist = values.split(DOMAIN_LIST_SEPARATOR)
+ self.domain_blacklist.reject! { |d| d.empty? }
+ self.domain_blacklist
end
- def restricted_signup_domains_raw=(values)
- self.restricted_signup_domains = []
- self.restricted_signup_domains = values.split(
- /\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace
- | # or
- \s # any whitespace character
- | # or
- [\r\n] # any number of newline characters
- /x)
- self.restricted_signup_domains.reject! { |d| d.empty? }
+ def domain_blacklist_file=(file)
+ self.domain_blacklist_raw = file.read
end
def runners_registration_token
diff --git a/app/models/user.rb b/app/models/user.rb
index 975e935fa20..7cbd97c0069 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -111,7 +111,7 @@ class User < ActiveRecord::Base
validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
before_validation :generate_password, on: :create
- before_validation :restricted_signup_domains, on: :create
+ before_validation :signup_domain_valid?, on: :create
before_validation :sanitize_attrs
before_validation :set_notification_email, if: ->(user) { user.email_changed? }
before_validation :set_public_email, if: ->(user) { user.public_email_changed? }
@@ -760,29 +760,6 @@ class User < ActiveRecord::Base
Project.where(id: events)
end
- def restricted_signup_domains
- email_domains = current_application_settings.restricted_signup_domains
-
- unless email_domains.blank?
- match_found = email_domains.any? do |domain|
- escaped = Regexp.escape(domain).gsub('\*', '.*?')
- regexp = Regexp.new "^#{escaped}$", Regexp::IGNORECASE
- email_domain = Mail::Address.new(self.email).domain
- email_domain =~ regexp
- end
-
- unless match_found
- self.errors.add :email,
- 'is not whitelisted. ' +
- 'Email domains valid for registration are: ' +
- email_domains.join(', ')
- return false
- end
- end
-
- true
- end
-
def can_be_removed?
!solo_owned_groups.present?
end
@@ -881,4 +858,40 @@ class User < ActiveRecord::Base
self.can_create_group = false
self.projects_limit = 0
end
+
+ def signup_domain_valid?
+ valid = true
+ error = nil
+
+ if current_application_settings.domain_blacklist_enabled?
+ blocked_domains = current_application_settings.domain_blacklist
+ if domain_matches?(blocked_domains, self.email)
+ error = 'is not from an allowed domain.'
+ valid = false
+ end
+ end
+
+ allowed_domains = current_application_settings.domain_whitelist
+ unless allowed_domains.blank?
+ if domain_matches?(allowed_domains, self.email)
+ valid = true
+ else
+ error = "is not whitelisted. Email domains valid for registration are: #{allowed_domains.join(', ')}"
+ valid = false
+ end
+ end
+
+ self.errors.add(:email, error) unless valid
+
+ valid
+ end
+
+ def domain_matches?(email_domains, email)
+ signup_domain = Mail::Address.new(email).domain
+ email_domains.any? do |domain|
+ escaped = Regexp.escape(domain).gsub('\*', '.*?')
+ regexp = Regexp.new "^#{escaped}$", Regexp::IGNORECASE
+ signup_domain =~ regexp
+ end
+ end
end
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index 538d8176ce7..23b52d08df7 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -109,7 +109,7 @@
Newly registered users will by default be external
%fieldset
- %legend Sign-in Restrictions
+ %legend Sign-up Restrictions
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
@@ -123,6 +123,49 @@
= f.check_box :send_user_confirmation_email
Send confirmation email on sign-up
.form-group
+ = f.label :domain_whitelist, 'Whitelisted domains for sign-ups', class: 'control-label col-sm-2'
+ .col-sm-10
+ = f.text_area :domain_whitelist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
+ .help-block ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com
+ .form-group
+ = f.label :domain_blacklist_enabled, 'Domain Blacklist', class: 'control-label col-sm-2'
+ .col-sm-10
+ .checkbox
+ = f.label :domain_blacklist_enabled do
+ = f.check_box :domain_blacklist_enabled
+ Enable domain blacklist for sign ups
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .radio
+ = label_tag :blacklist_type_file do
+ = radio_button_tag :blacklist_type, :file
+ .option-title
+ Upload blacklist file
+ .radio
+ = label_tag :blacklist_type_raw do
+ = radio_button_tag :blacklist_type, :raw, @application_setting.domain_blacklist.present? || @application_setting.domain_blacklist.blank?
+ .option-title
+ Enter blacklist manually
+ .form-group.blacklist-file
+ = f.label :domain_blacklist_file, 'Blacklist file', class: 'control-label col-sm-2'
+ .col-sm-10
+ = f.file_field :domain_blacklist_file, class: 'form-control', accept: '.txt,.conf'
+ .help-block Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines or commas for multiple entries.
+ .form-group.blacklist-raw
+ = f.label :domain_blacklist, 'Blacklisted domains for sign-ups', class: 'control-label col-sm-2'
+ .col-sm-10
+ = f.text_area :domain_blacklist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
+ .help-block Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com
+
+ .form-group
+ = f.label :after_sign_up_text, class: 'control-label col-sm-2'
+ .col-sm-10
+ = f.text_area :after_sign_up_text, class: 'form-control', rows: 4
+ .help-block Markdown enabled
+
+ %fieldset
+ %legend Sign-in Restrictions
+ .form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :signin_enabled do
@@ -148,11 +191,6 @@
= f.number_field :two_factor_grace_period, min: 0, class: 'form-control', placeholder: '0'
.help-block Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication
.form-group
- = f.label :restricted_signup_domains, 'Restricted domains for sign-ups', class: 'control-label col-sm-2'
- .col-sm-10
- = f.text_area :restricted_signup_domains_raw, placeholder: 'domain.com', class: 'form-control'
- .help-block Only users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com
- .form-group
= f.label :home_page_url, 'Home page URL', class: 'control-label col-sm-2'
.col-sm-10
= f.text_field :home_page_url, class: 'form-control', placeholder: 'http://company.example.com', :'aria-describedby' => 'home_help_block'
@@ -168,11 +206,6 @@
= f.text_area :sign_in_text, class: 'form-control', rows: 4
.help-block Markdown enabled
.form-group
- = f.label :after_sign_up_text, class: 'control-label col-sm-2'
- .col-sm-10
- = f.text_area :after_sign_up_text, class: 'form-control', rows: 4
- .help-block Markdown enabled
- .form-group
= f.label :help_page_text, class: 'control-label col-sm-2'
.col-sm-10
= f.text_area :help_page_text, class: 'form-control', rows: 4
@@ -352,4 +385,4 @@
.form-actions
- = f.submit 'Save', class: 'btn btn-save'
+ = f.submit 'Save', class: 'btn btn-save' \ No newline at end of file