diff --git a/app/controllers/concerns/epp/common.rb b/app/controllers/concerns/epp/common.rb index f30c09f4d..e417e8ab4 100644 --- a/app/controllers/concerns/epp/common.rb +++ b/app/controllers/concerns/epp/common.rb @@ -32,12 +32,15 @@ module Epp::Common @current_epp_user ||= EppUser.find(epp_session[:epp_user_id]) if epp_session[:epp_user_id] end - def handle_errors(error_code_map, obj) + def handle_epp_errors(error_code_map, obj) obj.errors.each do |key, err| error_code_map.each do |code, values| - has_error = Proc.new do |x| - x.is_a?(Array) ? obj.errors.added?(key, x[0], x[1]) : obj.errors.added?(key, x) + if x.is_a?(Array) + obj.errors.generate_message(key, x[0], x[1]) == err + else + obj.errors.generate_message(key, x) == err + end end if err.is_a?(Hash) diff --git a/app/helpers/epp/domains_helper.rb b/app/helpers/epp/domains_helper.rb index cf0f4af81..aae54521e 100644 --- a/app/helpers/epp/domains_helper.rb +++ b/app/helpers/epp/domains_helper.rb @@ -57,10 +57,11 @@ module Epp::DomainsHelper end def handle_errors - super({ + handle_epp_errors({ '2302' => [:epp_domain_taken, :epp_domain_reserved], '2306' => [:blank, [:out_of_range, {min: 1, max: 13}]], - '2303' => [:not_found] + '2303' => [:not_found], + '2005' => [:hostname_invalid] }, @domain ) end diff --git a/app/models/domain.rb b/app/models/domain.rb index 5aac31007..70e4381a1 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -20,6 +20,7 @@ class Domain < ActiveRecord::Base validates :name_dirty, domain_name: true, uniqueness: { message: :epp_domain_taken } validates :period, numericality: { only_integer: true, greater_than: 0, less_than: 100 } validates :name, :owner_contact, presence: true + validates_associated :nameservers def name=(value) value.strip! @@ -61,17 +62,38 @@ class Domain < ActiveRecord::Base ) end - def attach_nameservers(nameservers) - nameservers.each do |x| - self.nameservers << Nameserver.find_or_create_by(hostname: x) + def attach_nameservers(ns_list) + ns_list.each do |x| + self.nameservers.build(hostname: x) end - save! + + save + + add_child_collection_errors(:nameservers, :ns) validate_nameservers_count errors.empty? end + def add_child_collection_errors(attr_key, epp_obj_name) + send(attr_key).each do |obj| + obj.errors.keys.each do |key| + add_errors_with_value(attr_key, epp_obj_name, obj, key) + end + end + end + + def add_errors_with_value(attr_key, epp_obj_name, obj, key) + obj.errors[key].each do |x| + errors.add(attr_key, { + obj: epp_obj_name, + val: obj.send(key), + msg: x + }) + end + end + def validate_nameservers_count errors.add(:nameservers, :blank) if nameservers.empty? diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb index 356d4fffa..7c8134df6 100644 --- a/app/models/nameserver.rb +++ b/app/models/nameserver.rb @@ -1,4 +1,6 @@ class Nameserver < ActiveRecord::Base belongs_to :registrar has_and_belongs_to_many :domains + + validates :hostname, hostname: true end diff --git a/app/validators/hostname_validator.rb b/app/validators/hostname_validator.rb new file mode 100644 index 000000000..cb9bbdfef --- /dev/null +++ b/app/validators/hostname_validator.rb @@ -0,0 +1,13 @@ +class HostnameValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + if !self.class.validate_format(value) + record.errors.add(attribute, (options[:message] || :invalid)) + end + end + + class << self + def validate_format(value) + !!(value =~ /\A(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\z/) + end + end +end diff --git a/config/locales/en.yml b/config/locales/en.yml index 253adadf7..79cf90fdc 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -48,6 +48,12 @@ en: nameservers: blank: 'Required parameter missing - nameserver' out_of_range: 'Domain must have %{min}-%{max} nameservers' + hostname_invalid: 'Hostname is invalid' + nameserver: + attributes: + hostname: + invalid: 'Hostname is invalid' + errors: messages: diff --git a/spec/epp/domain_spec.rb b/spec/epp/domain_spec.rb index 34c8a5b41..79cc6a985 100644 --- a/spec/epp/domain_spec.rb +++ b/spec/epp/domain_spec.rb @@ -78,6 +78,12 @@ describe 'EPP Domain', epp: true do expect(response[:result_code]).to eq('2306') expect(response[:msg]).to eq('Domain must have 1-13 nameservers') end + + it 'returns error when invalid nameservers are present' do + response = epp_request('domains/create_w_invalid_nameservers.xml') + expect(response[:result_code]).to eq('2005') + expect(response[:msg]).to eq('Hostname is invalid') + end end context 'with juridical persion as an owner' do diff --git a/spec/epp/requests/domains/create_w_invalid_nameservers.xml b/spec/epp/requests/domains/create_w_invalid_nameservers.xml new file mode 100644 index 000000000..7569ff629 --- /dev/null +++ b/spec/epp/requests/domains/create_w_invalid_nameservers.xml @@ -0,0 +1,24 @@ + + + + + + example.ee + 1 + + invalid1- + -invalid2 + + jd1234 + sh8013 + sh8013 + sh801333 + + 2fooBAR + + + + ABC-12345 + +