diff --git a/app/models/concerns/domain/activatable.rb b/app/models/concerns/domain/activatable.rb new file mode 100644 index 000000000..58ff822d9 --- /dev/null +++ b/app/models/concerns/domain/activatable.rb @@ -0,0 +1,20 @@ +module Concerns::Domain::Activatable + extend ActiveSupport::Concern + + def active? + !inactive? + end + + def inactive? + statuses.include?(DomainStatus::INACTIVE) + end + + def activate + statuses.delete(DomainStatus::INACTIVE) + end + + def deactivate + return if inactive? + statuses << DomainStatus::INACTIVE + end +end diff --git a/app/models/depp/domain.rb b/app/models/depp/domain.rb index f181d0000..417159b39 100644 --- a/app/models/depp/domain.rb +++ b/app/models/depp/domain.rb @@ -40,13 +40,22 @@ module Depp keys = Domain.create_dnskeys_hash(domain_params) dns_hash[:_anonymus] = keys if keys.any? - xml = epp_xml.create({ - name: { value: domain_params[:name] }, - period: { value: domain_params[:period].to_s[0], attrs: { unit: domain_params[:period].to_s[1] } }, - ns: Domain.create_nameservers_hash(domain_params), - registrant: { value: domain_params[:registrant] }, - _anonymus: Domain.create_contacts_hash(domain_params) - }, dns_hash, Domain.construct_custom_params_hash(domain_params)) + if domain_params[:nameservers_attributes].select { |key, value| value['hostname'].present? }.any? + xml = epp_xml.create({ + name: { value: domain_params[:name] }, + period: { value: domain_params[:period].to_s[0], attrs: { unit: domain_params[:period].to_s[1] } }, + ns: Domain.create_nameservers_hash(domain_params), + registrant: { value: domain_params[:registrant] }, + _anonymus: Domain.create_contacts_hash(domain_params) + }, dns_hash, Domain.construct_custom_params_hash(domain_params)) + else + xml = epp_xml.create({ + name: { value: domain_params[:name] }, + period: { value: domain_params[:period].to_s[0], attrs: { unit: domain_params[:period].to_s[1] } }, + registrant: { value: domain_params[:registrant] }, + _anonymus: Domain.create_contacts_hash(domain_params) + }, dns_hash, Domain.construct_custom_params_hash(domain_params)) + end current_user.request(xml) end diff --git a/app/models/domain.rb b/app/models/domain.rb index 1bbecc62d..594a8d2cc 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -4,6 +4,7 @@ class Domain < ActiveRecord::Base include Versions # version/domain_version.rb include Statuses include Concerns::Domain::Expirable + include Concerns::Domain::Activatable has_paper_trail class_name: "DomainVersion", meta: { children: :children_log } @@ -694,8 +695,8 @@ class Domain < ActiveRecord::Base 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 + deactivate if nameservers.reject(&:marked_for_destruction?).empty? + activate if nameservers.reject(&:marked_for_destruction?).size >= Setting.ns_min_count end end # rubocop: enable Metrics/CyclomaticComplexity diff --git a/app/validators/domain_nameserver_validator.rb b/app/validators/domain_nameserver_validator.rb index b9a607bb9..55ceb1c96 100644 --- a/app/validators/domain_nameserver_validator.rb +++ b/app/validators/domain_nameserver_validator.rb @@ -1,10 +1,10 @@ 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 true if !Domain.nameserver_required? && values.empty? + return if values.size.between?(min, max) association = options[:association] || attribute record.errors.add(association, :out_of_range, { min: min, max: max }) diff --git a/app/views/registrar/domains/form_partials/_nameservers.haml b/app/views/registrar/domains/form_partials/_nameservers.haml index 557d28987..572821c6c 100644 --- a/app/views/registrar/domains/form_partials/_nameservers.haml +++ b/app/views/registrar/domains/form_partials/_nameservers.haml @@ -9,10 +9,11 @@ .panel-body .form-group .col-md-3.control-label - = label_tag "domain_nameservers_attributes_#{k}_hostname", t(:hostname), class: 'required' + = label_tag "domain_nameservers_attributes_#{k}_hostname", t(:hostname), + class: Domain.nameserver_required? ? 'required' : nil .col-md-7 = text_field_tag "domain[nameservers_attributes][#{k}][hostname]", v['hostname'], - class: 'form-control', required: true + class: 'form-control', required: Domain.nameserver_required? .form-group .col-md-3.control-label = label_tag "domain_nameservers_attributes_#{k}_ipv4", t(:ipv4) diff --git a/spec/models/concerns/domain/activatable_spec.rb b/spec/models/concerns/domain/activatable_spec.rb new file mode 100644 index 000000000..aeb5b0bfd --- /dev/null +++ b/spec/models/concerns/domain/activatable_spec.rb @@ -0,0 +1,68 @@ +require 'rails_helper' + +RSpec.describe Domain, db: false do + describe '#active?' do + context 'when :statuses does not contain :inactive' do + let(:domain) { described_class.new(statuses: []) } + + it 'returns true' do + expect(domain.active?).to be true + end + end + + context 'when :statuses contains :inactive' do + let(:domain) { described_class.new(statuses: [DomainStatus::INACTIVE]) } + + it 'returns false' do + expect(domain.active?).to be false + end + end + end + + describe '#inactive?' do + context 'when :statuses contains :inactive' do + let(:domain) { described_class.new(statuses: [DomainStatus::INACTIVE]) } + + it 'returns true' do + expect(domain.inactive?).to be true + end + end + + context 'when :statuses does not contain :inactive' do + let(:domain) { described_class.new(statuses: []) } + + it 'returns false' do + expect(domain.inactive?).to be false + end + end + end + + describe '#activate' do + let(:domain) { described_class.new(statuses: [DomainStatus::INACTIVE]) } + + it 'activates domain' do + domain.activate + expect(domain).to be_active + end + end + + describe '#deactivate' do + context 'when active' do + let(:domain) { described_class.new } + + it 'deactivates domain' do + domain.deactivate + expect(domain).to be_inactive + end + end + + context 'when inactive' do + let(:domain) { described_class.new(statuses: [DomainStatus::INACTIVE]) } + + it 'does not add :inactive status' do + domain.deactivate + expect(domain.statuses).to eq([DomainStatus::INACTIVE]) + end + end + end +end diff --git a/spec/requests/epp/domain/create_spec.rb b/spec/requests/epp/domain/create/optional_nameserver_spec.rb similarity index 59% rename from spec/requests/epp/domain/create_spec.rb rename to spec/requests/epp/domain/create/optional_nameserver_spec.rb index 1311e4033..2107486de 100644 --- a/spec/requests/epp/domain/create_spec.rb +++ b/spec/requests/epp/domain/create/optional_nameserver_spec.rb @@ -31,7 +31,7 @@ RSpec.describe 'EPP domain:create' do allow(Domain).to receive(:nameserver_required?).and_return(false) end - context 'when minimum nameserver count is not satisfied' do + context 'when minimum nameserver count requirement is not satisfied' do let(:request_xml) { <<-XML @@ -43,7 +43,6 @@ RSpec.describe 'EPP domain:create' do ns.test.com - 192.168.1.1 test @@ -122,77 +121,4 @@ RSpec.describe 'EPP domain:create' do 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/create/required_nameserver_spec.rb b/spec/requests/epp/domain/create/required_nameserver_spec.rb new file mode 100644 index 000000000..b1d4c6fc8 --- /dev/null +++ b/spec/requests/epp/domain/create/required_nameserver_spec.rb @@ -0,0 +1,100 @@ +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 required' do + before :example do + allow(Domain).to receive(:nameserver_required?).and_return(true) + Setting.ns_min_count = 1 + end + + context 'when minimum nameserver count requirement is satisfied' do + let(:request_xml) { <<-XML + + + + + + test.com + 1 + + + ns.test.com + + + 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 nameservers are 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/nameserver_add_spec.rb b/spec/requests/epp/domain/update/nameserver_add_spec.rb new file mode 100644 index 000000000..d6f886932 --- /dev/null +++ b/spec/requests/epp/domain/update/nameserver_add_spec.rb @@ -0,0 +1,92 @@ +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 + + context 'when nameserver count is less than minimum' do + let(:request_xml) { <<-XML + + + + + + test.com + + + + ns1.test.ee + + + + + + + + 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 + + + + + + + + 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 diff --git a/spec/requests/epp/domain/update/nameserver_remove_spec.rb b/spec/requests/epp/domain/update/nameserver_remove_spec.rb new file mode 100644 index 000000000..5ecc2f29a --- /dev/null +++ b/spec/requests/epp/domain/update/nameserver_remove_spec.rb @@ -0,0 +1,106 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:update' 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 + sign_in_to_epp_area + + allow(Domain).to receive(:nameserver_required?).and_return(false) + end + + context 'when remaining nameserver count is less than required minimum' do + let!(:domain) { create(:domain, name: 'test.com') } + let(:request_xml) { <<-XML + + + + + + test.com + + + + ns1.test.ee + + + + + + + + XML + } + + before :example do + Setting.ns_min_count = 2 + Setting.ns_max_count = 3 + + domain.nameservers << create(:nameserver, hostname: 'ns1.test.ee') + domain.nameservers << create(:nameserver, hostname: 'ns2.test.ee') + end + + 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!(:domain) { create(:domain, name: 'test.com') } + let(:request_xml) { <<-XML + + + + + + test.com + + + + ns1.test.ee + + + ns2.test.ee + + + + + + + + XML + } + + before :example do + domain.nameservers << create(:nameserver, hostname: 'ns1.test.ee') + domain.nameservers << create(:nameserver, hostname: 'ns2.test.ee') + domain.activate + domain.save! + end + + 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 + + describe 'domain' do + it 'has status of inactive' do + post '/epp/command/update', frame: request_xml + domain = Domain.find_by(name: 'test.com') + expect(domain.statuses).to include(DomainStatus::INACTIVE) + end + end + end +end diff --git a/spec/requests/epp/domain/update_spec.rb b/spec/requests/epp/domain/update_spec.rb deleted file mode 100644 index 6a31562f9..000000000 --- a/spec/requests/epp/domain/update_spec.rb +++ /dev/null @@ -1,193 +0,0 @@ -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