From c8b7ec8806d5e31207d63580e458f1dad35caa5b Mon Sep 17 00:00:00 2001 From: Sergei Tsoganov Date: Wed, 29 Jul 2026 11:41:04 +0300 Subject: [PATCH] Fix 500 error on contact create with invalid ident --- app/interactions/actions/contact_create.rb | 23 +++++++++++-- .../contact/ident/national_id_validator.rb | 16 +++------ .../contact/ident/reg_no_validator.rb | 17 +++------- .../epp/contact/create/base_test.rb | 33 +++++++++++++++++++ 4 files changed, 63 insertions(+), 26 deletions(-) diff --git a/app/interactions/actions/contact_create.rb b/app/interactions/actions/contact_create.rb index 782efdf9a4..5e2d603036 100644 --- a/app/interactions/actions/contact_create.rb +++ b/app/interactions/actions/contact_create.rb @@ -57,7 +57,24 @@ def maybe_validate_ident identifier = ::Contact::Ident.new(code: ident[:ident], type: ident[:ident_type], country_code: ident[:ident_country_code]) - identifier.validate + unless identifier.valid? + identifier.errors.details.each do |attr, error_details| + error_details.each do |error_detail| + ::Contact::Ident.epp_code_map.each do |epp_code, attr_to_error| + next unless attr_to_error.any? { |i| i == [attr, error_detail[:error]] } + + message = identifier.errors.generate_message(attr, error_detail[:error], error_detail) + message = identifier.errors.full_message(attr, message) + message = "#{identifier.model_name.human} #{message.camelize(:lower)}" if attr != :base + + contact.add_epp_error(epp_code, nil, attr.to_s, message) + end + end + end + @error = true + return + end + contact.identifier = identifier end @@ -84,6 +101,7 @@ def validate_ident_birthday end def maybe_company_is_relevant + return true if @error return true if ENV['allow_validate_business_contacts'] && ENV['allow_validate_business_contacts'] == 'false' return true unless contact.org? return true unless contact.ident_country_code == 'EE' @@ -91,6 +109,7 @@ def maybe_company_is_relevant company_status = contact.return_company_status return true if [Contact::REGISTERED, Contact::LIQUIDATED].include? company_status + contact.add_epp_error('2003', nil, 'ident', I18n.t('errors.messages.company_not_registered')) @error = true @@ -112,7 +131,7 @@ def commit def maybe_validate_contact return if @error || !contact.valid? - [:regex, :mx].each do |m| + %i[regex mx].each do |m| contact.verify_email(check_level: m, single_email: true) end end diff --git a/app/validators/contact/ident/national_id_validator.rb b/app/validators/contact/ident/national_id_validator.rb index 2fcf019b1e..2c86b0ccd3 100644 --- a/app/validators/contact/ident/national_id_validator.rb +++ b/app/validators/contact/ident/national_id_validator.rb @@ -1,22 +1,14 @@ class Contact::Ident::NationalIdValidator < ActiveModel::EachValidator - def self.country_specific_validations - { - Country.new('EE') => proc { |code| Isikukood.new(code).valid? }, - } - end + COUNTRY_SPECIFIC_VALIDATIONS = { + 'EE' => proc { |code| Isikukood.new(code).valid? }, + }.freeze def validate_each(record, attribute, value) - validation = validation_for(record.country) + validation = COUNTRY_SPECIFIC_VALIDATIONS[record.country_code] return unless validation valid = validation.call(value) record.errors.add(attribute, :invalid_national_id, country: record.country) unless valid end - - private - - def validation_for(country) - self.class.country_specific_validations[country] - end end diff --git a/app/validators/contact/ident/reg_no_validator.rb b/app/validators/contact/ident/reg_no_validator.rb index 138aab56a2..7082bc481b 100644 --- a/app/validators/contact/ident/reg_no_validator.rb +++ b/app/validators/contact/ident/reg_no_validator.rb @@ -1,22 +1,15 @@ class Contact::Ident::RegNoValidator < ActiveModel::EachValidator - def self.country_specific_formats - { - Country.new('EE') => /\A[0-9]{8}\z/, - } - end + COUNTRY_SPECIFIC_FORMATS = { + 'EE' => /\A[0-9]{8}\z/, + }.freeze def validate_each(record, attribute, value) - format = format_for(record.country) + format = COUNTRY_SPECIFIC_FORMATS[record.country_code] return unless format return if value.match?(format) - record.errors.add(attribute, :invalid_reg_no, country: record.country) - end - private - - def format_for(country) - self.class.country_specific_formats[country] + record.errors.add(attribute, :invalid_reg_no, country: record.country) end end diff --git a/test/integration/epp/contact/create/base_test.rb b/test/integration/epp/contact/create/base_test.rb index ec8cdba3a4..574bb8f483 100644 --- a/test/integration/epp/contact/create/base_test.rb +++ b/test/integration/epp/contact/create/base_test.rb @@ -241,6 +241,39 @@ def test_responses_with_error_on_invalid_birthday_date # assert_epp_response :parameter_value_syntax_error # end + def test_returns_error_when_org_ident_contains_country_prefix + request_xml = <<-XML + + + + + + + Test Org + + +372.1234567 + org@registrar.test + + + + + EE10294687 + + + + + XML + + assert_no_difference 'Contact.count' do + post epp_create_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + end + + response_xml = Nokogiri::XML(response.body) + assert_correct_against_schema response_xml + assert_epp_response :parameter_value_syntax_error + end + def test_respects_custom_code name = 'new' code = 'custom-id'