diff --git a/app/models/domain.rb b/app/models/domain.rb
index edc8e02cc..1bbecc62d 100644
--- a/app/models/domain.rb
+++ b/app/models/domain.rb
@@ -141,7 +141,7 @@ class Domain < ActiveRecord::Base
false
end
- validates :nameservers, object_count: {
+ validates :nameservers, domain_nameserver: {
min: -> { Setting.ns_min_count },
max: -> { Setting.ns_max_count }
}
@@ -692,6 +692,11 @@ class Domain < ActiveRecord::Base
p_d = statuses.include?(DomainStatus::PENDING_DELETE)
s_h = (statuses & [DomainStatus::SERVER_MANUAL_INZONE, DomainStatus::SERVER_HOLD]).empty?
statuses << DomainStatus::SERVER_HOLD if p_d && s_h
+
+ if !self.class.nameserver_required?
+ statuses << DomainStatus::INACTIVE if nameservers.empty?
+ statuses.delete(DomainStatus::INACTIVE) if nameservers.size >= Setting.ns_min_count
+ end
end
# rubocop: enable Metrics/CyclomaticComplexity
# rubocop: enable Metrics/PerceivedComplexity
diff --git a/app/models/epp/domain.rb b/app/models/epp/domain.rb
index 155d70c18..6a2edf5ed 100644
--- a/app/models/epp/domain.rb
+++ b/app/models/epp/domain.rb
@@ -71,12 +71,6 @@ class Epp::Domain < Domain
[:base, :required_parameter_missing_reserved]
],
'2004' => [ # Parameter value range error
- [:nameservers, :out_of_range,
- {
- min: Setting.ns_min_count,
- max: Setting.ns_max_count
- }
- ],
[:dnskeys, :out_of_range,
{
min: Setting.dnskeys_min_count,
@@ -124,7 +118,13 @@ class Epp::Domain < Domain
[:registrant, :cannot_be_missing]
],
'2308' => [
- [:base, :domain_name_blocked, { value: { obj: 'name', val: name_dirty } }]
+ [:base, :domain_name_blocked, { value: { obj: 'name', val: name_dirty } }],
+ [:nameservers, :out_of_range,
+ {
+ min: Setting.ns_min_count,
+ max: Setting.ns_max_count
+ }
+ ],
]
}
end
diff --git a/app/validators/domain_nameserver_validator.rb b/app/validators/domain_nameserver_validator.rb
new file mode 100644
index 000000000..b9a607bb9
--- /dev/null
+++ b/app/validators/domain_nameserver_validator.rb
@@ -0,0 +1,12 @@
+class DomainNameserverValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ return true if !Domain.nameserver_required? && value.empty?
+
+ min, max = options[:min].call, options[:max].call
+ values = value.reject(&:marked_for_destruction?)
+
+ return if values.size.between?(min, max)
+ association = options[:association] || attribute
+ record.errors.add(association, :out_of_range, { min: min, max: max })
+ end
+end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 92158b6fd..8e4d26b9b 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -97,7 +97,7 @@ en:
out_of_range: 'Tech contacts count must be between %{min}-%{max}'
nameservers:
invalid: 'Nameservers are invalid'
- out_of_range: 'Nameservers count must be between %{min}-%{max}'
+ out_of_range: Data management policy violation; Nameserver count must be between %{min}-%{max} for active domains
not_found: 'Nameserver was not found'
taken: 'Nameserver already exists on this domain'
less_than_or_equal_to: 'Nameservers count must be less than or equal to %{count}'
diff --git a/spec/factories/domain.rb b/spec/factories/domain.rb
index 5a396362d..534670ce0 100644
--- a/spec/factories/domain.rb
+++ b/spec/factories/domain.rb
@@ -7,7 +7,6 @@ FactoryGirl.define do
registrant
after :build do |domain|
- domain.nameservers << FactoryGirl.build_pair(:nameserver)
domain.admin_domain_contacts << FactoryGirl.build(:admin_domain_contact)
domain.tech_domain_contacts << FactoryGirl.build(:tech_domain_contact)
end
diff --git a/spec/models/domain_spec.rb b/spec/models/domain_spec.rb
index 8b1554b68..555cf48e1 100644
--- a/spec/models/domain_spec.rb
+++ b/spec/models/domain_spec.rb
@@ -37,7 +37,6 @@ RSpec.describe Domain do
@domain.valid?
@domain.errors.full_messages.should match_array([
"Admin domain contacts Admin contacts count must be between 1-10",
- "Nameservers Nameservers count must be between 2-11",
"Period Period is not a number",
"Registrant Registrant is missing",
"Registrar Registrar is missing"
@@ -704,6 +703,71 @@ RSpec.describe Domain, db: false do
it { is_expected.to alias_attribute(:force_delete_time, :force_delete_at) }
it { is_expected.to alias_attribute(:outzone_time, :outzone_at) }
+ describe 'nameserver validation', db: true do
+ let(:domain) { described_class.new }
+
+ it 'rejects less than min' do
+ Setting.ns_min_count = 2
+ domain.nameservers.build(FactoryGirl.attributes_for(:nameserver))
+ domain.validate
+ expect(domain.errors).to have_key(:nameservers)
+ end
+
+ it 'rejects more than max' do
+ Setting.ns_min_count = 1
+ Setting.ns_max_count = 1
+ domain.nameservers.build(FactoryGirl.attributes_for(:nameserver))
+ domain.nameservers.build(FactoryGirl.attributes_for(:nameserver))
+ domain.validate
+ expect(domain.errors).to have_key(:nameservers)
+ end
+
+ it 'accepts min' do
+ Setting.ns_min_count = 1
+ domain.nameservers.build(FactoryGirl.attributes_for(:nameserver))
+ domain.validate
+ expect(domain.errors).to_not have_key(:nameservers)
+ end
+
+ it 'accepts max' do
+ Setting.ns_min_count = 1
+ Setting.ns_max_count = 2
+ domain.nameservers.build(FactoryGirl.attributes_for(:nameserver))
+ domain.nameservers.build(FactoryGirl.attributes_for(:nameserver))
+ domain.validate
+ expect(domain.errors).to_not have_key(:nameservers)
+ end
+
+ context 'when nameserver is optional' do
+ before :example do
+ allow(Domain).to receive(:nameserver_required?).and_return(false)
+ end
+
+ it 'rejects less than min' do
+ Setting.ns_min_count = 2
+ domain.nameservers.build(FactoryGirl.attributes_for(:nameserver))
+ domain.validate
+ expect(domain.errors).to have_key(:nameservers)
+ end
+
+ it 'accepts absent' do
+ domain.validate
+ expect(domain.errors).to_not have_key(:nameservers)
+ end
+ end
+
+ context 'when nameserver is required' do
+ before :example do
+ allow(Domain).to receive(:nameserver_required?).and_return(true)
+ end
+
+ it 'rejects absent' do
+ domain.validate
+ expect(domain.errors).to have_key(:nameservers)
+ end
+ end
+ end
+
describe '::nameserver_required?' do
before do
Setting.nameserver_required = 'test'
diff --git a/spec/requests/epp/domain/create_spec.rb b/spec/requests/epp/domain/create_spec.rb
new file mode 100644
index 000000000..1311e4033
--- /dev/null
+++ b/spec/requests/epp/domain/create_spec.rb
@@ -0,0 +1,198 @@
+require 'rails_helper'
+
+RSpec.describe 'EPP domain:create' do
+ subject(:response_xml) { Nokogiri::XML(response.body) }
+ subject(:response_code) { response_xml.xpath('//xmlns:result').first['code'] }
+ subject(:response_description) { response_xml.css('result msg').text }
+
+ before :example do
+ travel_to Time.zone.parse('05.07.2010')
+
+ registrar = create(:registrar)
+ user = create(:api_user_epp, registrar: registrar)
+ create(:account, registrar: registrar, balance: 1.0)
+
+ create(:contact, code: 'test')
+
+ create(:pricelist,
+ category: 'com',
+ duration: '1year',
+ price: 1.to_money,
+ operation_category: 'create',
+ valid_from: Time.zone.parse('05.07.2010'),
+ valid_to: Time.zone.parse('05.07.2010')
+ )
+
+ sign_in_to_epp_area(user: user)
+ end
+
+ context 'when nameserver is optional' do
+ before :example do
+ allow(Domain).to receive(:nameserver_required?).and_return(false)
+ end
+
+ context 'when minimum nameserver count is not satisfied' do
+ let(:request_xml) { <<-XML
+
+
+
+
+
+ test.com
+ 1
+
+
+ ns.test.com
+ 192.168.1.1
+
+
+ test
+ test
+ test
+
+
+
+
+ #{Base64.encode64('a' * 5000)}
+
+
+
+
+ XML
+ }
+
+ before :example do
+ Setting.ns_min_count = 2
+ end
+
+ it 'returns epp code of 2308' do
+ post '/epp/command/create', frame: request_xml
+ expect(response_code).to eq('2308')
+ end
+
+ it 'returns epp description' do
+ post '/epp/command/create', frame: request_xml
+
+ description = 'Data management policy violation;' \
+ " Nameserver count must be between #{Setting.ns_min_count}-#{Setting.ns_max_count}" \
+ ' for active domains [nameservers]'
+ expect(response_description).to eq(description)
+ end
+ end
+
+ context 'when nameserver is absent' do
+ let(:request_xml) { <<-XML
+
+
+
+
+
+ test.com
+ 1
+ test
+ test
+ test
+
+
+
+
+ #{Base64.encode64('a' * 5000)}
+
+
+
+
+ XML
+ }
+
+ it 'returns epp code of 1000' do
+ post '/epp/command/create', frame: request_xml
+ expect(response_code).to eq('1000'), "Expected EPP code of 1000, got #{response_code} (#{response_description})"
+ end
+
+ it 'creates new domain' do
+ expect { post '/epp/command/create', frame: request_xml }.to change { Domain.count }.from(0).to(1)
+ end
+
+ describe 'new domain' do
+ it 'has status of inactive' do
+ post '/epp/command/create', frame: request_xml
+ domain = Domain.find_by(name: 'test.com')
+ expect(domain.statuses).to include(DomainStatus::INACTIVE)
+ end
+ end
+ end
+ end
+
+ context 'when nameserver is required' do
+ before :example do
+ allow(Domain).to receive(:nameserver_required?).and_return(true)
+ Setting.ns_min_count = 1
+ end
+
+ context 'when nameserver is present' do
+ let(:request_xml) { <<-XML
+
+
+
+
+
+ test.com
+ 1
+
+
+ ns.test.com
+ 192.168.1.1
+
+
+ test
+ test
+ test
+
+
+
+
+ #{Base64.encode64('a' * 5000)}
+
+
+
+
+ XML
+ }
+
+ it 'returns epp code of 1000' do
+ post '/epp/command/create', frame: request_xml
+ expect(response_code).to eq('1000'), "Expected EPP code of 1000, got #{response_code} (#{response_description})"
+ end
+ end
+
+ context 'when nameserver is absent' do
+ let(:request_xml) { <<-XML
+
+
+
+
+
+ test.com
+ 1
+ test
+ test
+ test
+
+
+
+
+ #{Base64.encode64('a' * 5000)}
+
+
+
+
+ XML
+ }
+
+ it 'returns epp code of 2003' do
+ post '/epp/command/create', frame: request_xml
+ expect(response_code).to eq('2003')
+ end
+ end
+ end
+end
diff --git a/spec/requests/epp/domain/update_spec.rb b/spec/requests/epp/domain/update_spec.rb
new file mode 100644
index 000000000..6a31562f9
--- /dev/null
+++ b/spec/requests/epp/domain/update_spec.rb
@@ -0,0 +1,193 @@
+require 'rails_helper'
+
+RSpec.describe 'EPP domain:update' do
+ let!(:domain) { create(:domain, name: 'test.com') }
+ subject(:response_xml) { Nokogiri::XML(response.body) }
+ subject(:response_code) { response_xml.xpath('//xmlns:result').first['code'] }
+ subject(:response_description) { response_xml.css('result msg').text }
+
+ before :example do
+ sign_in_to_epp_area
+
+ allow(Domain).to receive(:nameserver_required?).and_return(false)
+ Setting.ns_min_count = 2
+ Setting.ns_max_count = 3
+ end
+
+ describe 'nameserver add' do
+ context 'when nameserver count is less than minimum' do
+ let(:request_xml) { <<-XML
+
+
+
+
+
+ test.com
+
+
+
+ ns1.test.ee
+
+
+
+
+
+
+
+
+ #{Base64.encode64('a' * 5000)}
+
+
+
+
+ XML
+ }
+
+ it 'returns epp code of 2308' do
+ post '/epp/command/update', frame: request_xml
+ expect(response_code).to eq('2308'), "Expected EPP code of 2308, got #{response_code} (#{response_description})"
+ end
+
+ it 'returns epp description' do
+ post '/epp/command/update', frame: request_xml
+
+ description = 'Data management policy violation;' \
+ " Nameserver count must be between #{Setting.ns_min_count}-#{Setting.ns_max_count}" \
+ ' for active domains [nameservers]'
+ expect(response_description).to eq(description)
+ end
+ end
+
+ context 'when nameserver count satisfies required minimum' do
+ let!(:domain) { create(:domain, name: 'test.com') }
+ let(:request_xml) { <<-XML
+
+
+
+
+
+ test.com
+
+
+
+ ns1.test.ee
+
+
+ ns2.test.ee
+
+
+
+
+
+
+
+
+ #{Base64.encode64('a' * 5000)}
+
+
+
+
+ XML
+ }
+
+ it 'returns epp code of 1000' do
+ post '/epp/command/update', frame: request_xml
+ expect(response_code).to eq('1000'), "Expected EPP code of 1000, got #{response_code} (#{response_description})"
+ end
+
+ it 'removes inactive status' do
+ post '/epp/command/update', frame: request_xml
+
+ domain = Domain.find_by(name: 'test.com')
+ expect(domain.statuses).to_not include(DomainStatus::INACTIVE)
+ end
+ end
+ end
+
+ describe 'nameserver remove' do
+ before :example do
+ domain.nameservers << create(:nameserver, hostname: 'ns1.test.ee')
+ domain.nameservers << create(:nameserver, hostname: 'ns2.test.ee')
+ end
+
+ context 'when nameserver count is less than minimum' do
+ let(:request_xml) { <<-XML
+
+
+
+
+
+ test.com
+
+
+
+ ns1.test.ee
+
+
+
+
+
+
+
+
+ #{Base64.encode64('a' * 5000)}
+
+
+
+
+ XML
+ }
+
+ it 'returns epp code of 2308' do
+ post '/epp/command/update', frame: request_xml
+ expect(response_code).to eq('2308'), "Expected EPP code of 2308, got #{response_code} (#{response_description})"
+ end
+
+ it 'returns epp description' do
+ post '/epp/command/update', frame: request_xml
+
+ description = 'Data management policy violation;' \
+ " Nameserver count must be between #{Setting.ns_min_count}-#{Setting.ns_max_count}" \
+ ' for active domains [nameservers]'
+ expect(response_description).to eq(description)
+ end
+ end
+
+ context 'when all nameservers are removed' do
+ let(:request_xml) { <<-XML
+
+
+
+
+
+ test.com
+
+
+
+ ns1.test.ee
+
+
+ ns2.test.ee
+
+
+
+
+
+
+
+
+ #{Base64.encode64('a' * 5000)}
+
+
+
+
+ XML
+ }
+
+ it 'returns epp code of 1000' do
+ post '/epp/command/update', frame: request_xml
+ expect(response_code).to eq('2308'), "Expected EPP code of 1000, got #{response_code} (#{response_description})"
+ end
+ end
+ end
+end
diff --git a/spec/support/settings.rb b/spec/support/settings.rb
index 7a5aebf3b..f5d0f934d 100644
--- a/spec/support/settings.rb
+++ b/spec/support/settings.rb
@@ -10,6 +10,8 @@ RSpec.configure do |config|
Setting.dnskeys_min_count = 0
Setting.dnskeys_max_count = 9
+
+ Setting.nameserver_required = false
Setting.ns_min_count = 2
Setting.ns_max_count = 11