diff --git a/app/controllers/epp/base_controller.rb b/app/controllers/epp/base_controller.rb index 12efbd1d3..520b97c4f 100644 --- a/app/controllers/epp/base_controller.rb +++ b/app/controllers/epp/base_controller.rb @@ -21,12 +21,22 @@ module Epp rescue_from StandardError, with: :respond_with_command_failed_error rescue_from AuthorizationError, with: :respond_with_authorization_error rescue_from ActiveRecord::RecordNotFound, with: :respond_with_object_does_not_exist_error + rescue_from Shunter::ThrottleError, with: :respond_with_session_limit_exceeded_error + before_action :set_paper_trail_whodunnit skip_before_action :validate_against_schema protected + def respond_with_session_limit_exceeded_error(exception) + epp_errors.add(:epp_errors, + code: '2502', + message: 'Session limit exceeded, try again later') + handle_errors + log_exception(exception) + end + def respond_with_command_failed_error(exception) epp_errors.add(:epp_errors, code: '2400', @@ -51,6 +61,11 @@ module Epp private + def throttled_user + authorize!(:throttled_user, @domain) unless current_user + current_user + end + def wrap_exceptions yield rescue CanCan::AccessDenied diff --git a/app/controllers/epp/contacts_controller.rb b/app/controllers/epp/contacts_controller.rb index 10250563c..5509507d3 100644 --- a/app/controllers/epp/contacts_controller.rb +++ b/app/controllers/epp/contacts_controller.rb @@ -5,6 +5,9 @@ module Epp before_action :find_contact, only: [:info, :update, :delete] before_action :find_password, only: [:info, :update, :delete] + THROTTLED_ACTIONS = %i[info renew update transfer delete].freeze + include Shunter::Integration::Throttle + def info authorize! :info, @contact, @password render_epp_response 'epp/contacts/info' diff --git a/app/controllers/epp/domains_controller.rb b/app/controllers/epp/domains_controller.rb index 49ea43ae0..a05b56531 100644 --- a/app/controllers/epp/domains_controller.rb +++ b/app/controllers/epp/domains_controller.rb @@ -134,11 +134,6 @@ module Epp private - def throttled_user - authorize!(:throttled_user, @domain) unless current_user - current_user - end - def validate_info @prefix = 'info > info >' requires('name') diff --git a/config/application.yml.sample b/config/application.yml.sample index 5b01624cf..b8b9b12d0 100644 --- a/config/application.yml.sample +++ b/config/application.yml.sample @@ -198,6 +198,7 @@ test: dnssec_resolver_ips: 8.8.8.8, 8.8.4.4 legal_documents_dir: 'test/fixtures/files' shunter_default_adapter: "Shunter::Adapters::Memory" + shunter_enabled: "false" openssl_config_path: 'test/fixtures/files/test_ca/openssl.cnf' crl_dir: 'test/fixtures/files/test_ca/crl' diff --git a/test/integration/epp/domain/info/base_test.rb b/test/integration/epp/domain/info/base_test.rb index da3be1d38..99de33f29 100644 --- a/test/integration/epp/domain/info/base_test.rb +++ b/test/integration/epp/domain/info/base_test.rb @@ -1,6 +1,11 @@ require 'test_helper' class EppDomainInfoBaseTest < EppTestCase + setup do + adapter = ENV["shunter_default_adapter"].constantize.new + adapter&.clear! + end + def test_returns_valid_response assert_equal 'john-001', contacts(:john).code domains(:shop).update_columns(statuses: [DomainStatus::OK], @@ -180,6 +185,61 @@ class EppDomainInfoBaseTest < EppTestCase assert_correct_against_schema response_xml end + def test_returns_valid_response_if_not_throttled + domain = domains(:shop) + + request_xml = <<-XML + + + + + + #{domain.name} + + + + + XML + + post epp_info_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + + response_xml = Nokogiri::XML(response.body) + assert_epp_response :completed_successfully + assert_correct_against_schema response_xml + end + + def test_returns_error_response_if_throttled + ENV["shunter_default_threshold"] = '1' + ENV["shunter_enabled"] = 'true' + domain = domains(:shop) + + request_xml = <<-XML + + + + + + #{domain.name} + + + + + XML + + post epp_info_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + + post epp_info_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + + response_xml = Nokogiri::XML(response.body) + assert_epp_response :session_limit_exceeded_server_closing_connection + assert_correct_against_schema response_xml + ENV["shunter_default_threshold"] = '10000' + ENV["shunter_enabled"] = 'false' + end + def test_returns_valid_response_if_release_prohibited domain = domains(:shop) domain.update_columns(statuses: [DomainStatus::SERVER_RELEASE_PROHIBITED],