diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 337c92e43..826eaf399 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -113,6 +113,18 @@ def set_current_user
end
end
+ def current_user_country
+ remote_ip = ENV.fetch('MOCK_IP') { Rails.env.production? ? request.remote_ip : '130.88.0.0' }
+ Locator.instance.lookup(remote_ip)&.dig('country')
+ end
+
+ def from_blocked_country?
+ TeSS::Config.blocked_countries.present? &&
+ TeSS::Config.blocked_countries.include?(current_user_country['iso_code'].downcase)
+ end
+
+ helper_method :current_user_country, :from_blocked_country?
+
protected
def configure_permitted_parameters
diff --git a/app/controllers/tess_devise/registrations_controller.rb b/app/controllers/tess_devise/registrations_controller.rb
index b9ef521cb..80fcca377 100644
--- a/app/controllers/tess_devise/registrations_controller.rb
+++ b/app/controllers/tess_devise/registrations_controller.rb
@@ -1,6 +1,7 @@
class TessDevise::RegistrationsController < Devise::RegistrationsController
# Inspired by http://stackoverflow.com/questions/3546289/override-devise-registrations-controller
before_action :check_captcha, only: :create
+ before_action :check_country_blocked, only: [:create, :new]
before_action :set_breadcrumbs, only: :edit
# Set the after update path to be user's show page
@@ -30,6 +31,10 @@ def check_captcha
end
end
+ def check_country_blocked
+ head :forbidden if from_blocked_country?
+ end
+
def set_breadcrumbs
add_base_breadcrumbs('users')
@breadcrumbs += [{ name: @user.name, url: user_path(@user) }, { name: 'Manage Account' }]
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index fe260bb77..de1592cc4 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -691,9 +691,4 @@ def unverified_notice(resource)
content_tag('div', t('warnings.unverified', resource_type: resource.model_name.human.downcase),
class: 'alert alert-warning mb-4 unverified-notice')
end
-
- def current_user_country
- remote_ip = ENV.fetch('MOCK_IP') { Rails.env.production? ? request.remote_ip : '130.88.0.0' }
- Locator.instance.lookup(remote_ip)&.dig('country')
- end
end
diff --git a/app/views/layouts/_login_menu.html.erb b/app/views/layouts/_login_menu.html.erb
index 70a06870e..55a26b63e 100644
--- a/app/views/layouts/_login_menu.html.erb
+++ b/app/views/layouts/_login_menu.html.erb
@@ -14,7 +14,7 @@
<%= link_to t('authentication.password.title'), new_user_session_path %>
- <% if TeSS::Config.feature['registration'] %>
+ <% if TeSS::Config.feature['registration'] && !from_blocked_country? %>
<%= link_to "Register", new_user_registration_path %>
diff --git a/config/tess.example.yml b/config/tess.example.yml
index c0d65aec6..f86cd74db 100644
--- a/config/tess.example.yml
+++ b/config/tess.example.yml
@@ -15,6 +15,8 @@ default: &default
require_cookie_consent: true
blocked_domains:
- !ruby/regexp '/bad-domain\.example/'
+ blocked_countries: # Block registration from the following ISO 3166-1 alpha-2 codes
+ # - gb
sentry_dsn:
csp_report_uri:
site:
diff --git a/test/controllers/static_controller_test.rb b/test/controllers/static_controller_test.rb
index 7d3f5c499..aeea5eb8e 100644
--- a/test/controllers/static_controller_test.rb
+++ b/test/controllers/static_controller_test.rb
@@ -311,4 +311,20 @@ class StaticControllerTest < ActionController::TestCase
end
end
end
+
+ test 'should not show registration button if disabled for country' do
+ with_settings({ blocked_countries: ['gb'] }) do
+ Locator.instance.stub(:lookup, { 'country' => { 'iso_code' => 'GB' } }) do
+ get :home
+ assert_response :success
+ assert_select '.dropdown-item a', text: 'Register', count: 0
+ end
+
+ Locator.instance.stub(:lookup, { 'country' => { 'iso_code' => 'FR' } }) do
+ get :home
+ assert_response :success
+ assert_select '.dropdown-item a', text: 'Register', count: 1
+ end
+ end
+ end
end
diff --git a/test/controllers/tess_devise/registrations_controller_test.rb b/test/controllers/tess_devise/registrations_controller_test.rb
index 3a4ec76f2..6cc0e42e4 100644
--- a/test/controllers/tess_devise/registrations_controller_test.rb
+++ b/test/controllers/tess_devise/registrations_controller_test.rb
@@ -124,5 +124,45 @@ class RegistrationsControllerTest < ActionController::TestCase
put :update, params: { user: { username: 'cooldude99' } }
assert_redirected_to assigns(:user)
end
+
+ test 'should not register user from blocked country' do
+ assert_no_difference('User.count') do
+ Locator.instance.stub(:lookup, { 'country' => { 'iso_code' => 'GB' } }) do
+ with_settings({ blocked_countries: ['gb'] }) do
+ post :create, params: {
+ user: {
+ username: 'mileyfan1997',
+ email: 'h4nn4hm0nt4n4@example.com',
+ password: '12345678',
+ password_confirmation: '12345678',
+ processing_consent: '1'
+ }
+ }
+ end
+
+ assert_response :forbidden
+ end
+ end
+ end
+
+ test 'should register user if country not blocked' do
+ assert_difference('User.count') do
+ Locator.instance.stub(:lookup, { 'country' => { 'iso_code' => 'FR' } }) do
+ with_settings({ blocked_countries: ['gb'] }) do
+ post :create, params: {
+ user: {
+ username: 'mileyfan1997',
+ email: 'h4nn4hm0nt4n4@example.com',
+ password: '12345678',
+ password_confirmation: '12345678',
+ processing_consent: '1'
+ }
+ }
+ end
+
+ assert_redirected_to root_path
+ end
+ end
+ end
end
end