diff --git a/app/models/domain.rb b/app/models/domain.rb index 259cf4267..172ab2039 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -107,7 +107,6 @@ class Domain < ActiveRecord::Base validates :period, numericality: { only_integer: true } validates :registrant, :registrar, presence: true - validate :validate_period validate :validate_reservation def validate_reservation return if persisted? || !in_reserved_list? @@ -229,12 +228,6 @@ class Domain < ActiveRecord::Base end class << self - def convert_period_to_time(period, unit) - return (period.to_i / 365).years if unit == 'd' - return (period.to_i / 12).years if unit == 'm' - return period.to_i.years if unit == 'y' - end - def included includes( :registrant, @@ -450,18 +443,16 @@ class Domain < ActiveRecord::Base self.delete_at = nil end - def pricelist(operation, period_i = nil, unit = nil) + def pricelist(operation_category, period_i = nil, unit = nil) period_i ||= period unit ||= period_unit - # TODO: test if name.scan(/\.(.+)\z/).first.first is faster - zone = name.split('.').drop(1).join('.') + zone_name = name.split('.').drop(1).join('.') + zone = DNS::Zone.find_by(origin: zone_name) - p = period_i / 365 if unit == 'd' - p = period_i / 12 if unit == 'm' - p = period_i if unit == 'y' + duration = "P#{period_i}#{unit.upcase}" - Pricelist.pricelist_for(zone, operation, "#{p}year".pluralize(p)) + Billing::Price.price_for(zone, operation_category, duration) end ### VALIDATIONS ### @@ -476,19 +467,6 @@ class Domain < ActiveRecord::Base end end - def validate_period - return unless period.present? - if period_unit == 'd' - valid_values = %w(365 730 1095) - elsif period_unit == 'm' - valid_values = %w(12 24 36) - else - valid_values = %w(1 2 3) - end - - errors.add(:period, :out_of_range) unless valid_values.include?(period.to_s) - end - # used for highlighting form tabs def parent_valid? assoc_errors = errors.keys.select { |x| x.match(/\./) } diff --git a/app/models/epp/domain.rb b/app/models/epp/domain.rb index 33062cc3d..563923af0 100644 --- a/app/models/epp/domain.rb +++ b/app/models/epp/domain.rb @@ -55,7 +55,12 @@ class Epp::Domain < Domain domain.attach_default_contacts domain.registered_at = Time.zone.now domain.valid_from = Time.zone.now - domain.valid_to = domain.valid_from.beginning_of_day + convert_period_to_time(domain.period, domain.period_unit) + 1.day + + period = domain.period.to_i + plural_period_unit_name = (domain.period_unit == 'm' ? 'months' : 'years').to_sym + expire_time = (Time.zone.now.advance(plural_period_unit_name => period) + 1.day).beginning_of_day + domain.expire_time = expire_time + domain end end @@ -109,7 +114,6 @@ class Epp::Domain < Domain [:base, :domain_status_prohibits_operation] ], '2306' => [ # Parameter policy error - [:period, :out_of_range, { value: { obj: 'period', val: period } }], [:base, :ds_data_with_key_not_allowed], [:base, :ds_data_not_allowed], [:base, :key_data_not_allowed], @@ -588,8 +592,6 @@ class Epp::Domain < Domain save(validate: false) end - ### RENEW ### - def renew(cur_exp_date, period, unit = 'y') @is_renewal = true validate_exp_dates(cur_exp_date) @@ -597,19 +599,11 @@ class Epp::Domain < Domain add_epp_error('2105', nil, nil, I18n.t('object_is_not_eligible_for_renewal')) unless renewable? return false if errors.any? - p = self.class.convert_period_to_time(period, unit) - renewed_expire_time = valid_to + p + period = period.to_i + plural_period_unit_name = (unit == 'm' ? 'months' : 'years').to_sym + renewed_expire_time = valid_to.advance(plural_period_unit_name => period.to_i) - # Change it when Pricelist model periods change - max_reg_time = 4.years.from_now - - if renewed_expire_time >= max_reg_time - add_epp_error('2105', nil, nil, I18n.t('epp.domains.object_is_not_eligible_for_renewal', - max_date: max_reg_time.to_date.to_s(:db))) - return false if errors.any? - end - - self.valid_to = renewed_expire_time + self.expire_time = renewed_expire_time self.outzone_at = nil self.delete_at = nil self.period = period diff --git a/config/locales/en.yml b/config/locales/en.yml index a512cef3f..f6355d807 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -104,7 +104,6 @@ en: less_than_or_equal_to: 'Nameservers count must be less than or equal to %{count}' greater_than_or_equal_to: 'Nameservers count must be greater than or equal to %{count}' period: - out_of_range: 'Period must add up to 1, 2 or 3 years' not_a_number: 'Period is not a number' not_an_integer: 'Period must be an integer' auth_info: diff --git a/doc/epp/domain.md b/doc/epp/domain.md index d6c32467d..cd9de65b8 100644 --- a/doc/epp/domain.md +++ b/doc/epp/domain.md @@ -16,7 +16,7 @@ Domain name mapping protocol short version: 1 Attribute: xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd" 1 Domain name. Can contain unicode characters. 0-1 Registration period for domain. - Must add up to 1 / 2 / 3 years. + Must add up to 3m, 6m, 9m, 1y, 2y, 3y, 4y, 5y, 6y, 7y, 8y, 9y, 10y. Attribute: unit="y/m/d" Default is 1 year. 0-1 @@ -129,7 +129,8 @@ Domain name mapping protocol short version: 1 Domain name. Can contain unicode characters. 1 Current expiry date (ISO8601 format) 0-1 Registration period for domain. - Must add up to 1 / 2 / 3 years. Attribute: unit="y/m/d" + Must add up to 3m, 6m, 9m, 1y, 2y, 3y, 4y, 5y, 6y, 7y, 8y, 9y, 10y. + Attribute: unit="y/m/d" Default value is 1 year. 0-1 0-1 Attribute: xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd" diff --git a/spec/requests/epp/domain/create/default_period_spec.rb b/spec/requests/epp/domain/create/default_period_spec.rb new file mode 100644 index 000000000..05a1ab73a --- /dev/null +++ b/spec/requests/epp/domain/create/default_period_spec.rb @@ -0,0 +1,59 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:create', settings: false do + let(:request) { post '/epp/command/create', frame: request_xml } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:contact) { create(:contact, code: 'test') } + let!(:zone) { create(:zone, origin: 'test') } + let!(:registrar) { create(:registrar_with_unlimited_balance) } + let!(:price) { create(:price, + duration: '1 year', + price: Money.from_amount(1), + operation_category: 'create', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + let(:request_xml) { <<-XML + + + + + + test.test + test + + + + + #{valid_legal_document} + + + + + XML + } + + before :example do + travel_to Time.zone.parse('05.07.2010 10:30') + Setting.days_to_renew_domain_before_expire = 0 + sign_in_to_epp_area(user: user) + end + + context 'when period is absent' do + it 'creates domain' do + expect { request }.to change { Domain.count }.from(0).to(1) + end + + it 'uses default duration of 1 year' do + request + expire_time = (Time.zone.parse('05.07.2010') + 1.year + 1.day).beginning_of_day + expect(Domain.first.expire_time).to eq(expire_time) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end +end diff --git a/spec/requests/epp/domain/create/period_spec.rb b/spec/requests/epp/domain/create/period_spec.rb index 80de10e12..f2298680a 100644 --- a/spec/requests/epp/domain/create/period_spec.rb +++ b/spec/requests/epp/domain/create/period_spec.rb @@ -6,33 +6,6 @@ RSpec.describe 'EPP domain:create', settings: false do let!(:contact) { create(:contact, code: 'test') } let!(:zone) { create(:zone, origin: 'test') } let!(:registrar) { create(:registrar_with_unlimited_balance) } - let!(:price) { create(:price, - duration: '1 year', - price: Money.from_amount(1), - operation_category: 'create', - valid_from: Time.zone.parse('05.07.2010'), - valid_to: Time.zone.parse('05.07.2010'), - zone: zone) - } - let(:request_xml) { <<-XML - - - - - - test.test - test - - - - - #{valid_legal_document} - - - - - XML - } before :example do travel_to Time.zone.parse('05.07.2010 10:30') @@ -40,15 +13,91 @@ RSpec.describe 'EPP domain:create', settings: false do sign_in_to_epp_area(user: user) end - context 'when period is absent' do + context 'when period is 3 months' do + let!(:price) { create(:price, + duration: '3 months', + price: Money.from_amount(1), + operation_category: 'create', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + let(:request_xml) { <<-XML + + + + + + test.test + 3 + test + + + + + #{valid_legal_document} + + + + + XML + } + + it 'creates domain' do expect { request }.to change { Domain.count }.from(0).to(1) end - it 'uses default duration of 1 year' do + specify 'expire_time' do request - valid_to = (Time.zone.parse('05.07.2010') + 1.year + 1.day).beginning_of_day - expect(Domain.first.valid_to).to eq(valid_to) + expire_time = (Time.zone.parse('05.07.2010 10:30') + 3.months + 1.day).beginning_of_day + expect(Domain.first.expire_time).to eq(expire_time) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end + + context 'when period is 10 years' do + let!(:price) { create(:price, + duration: '10 years', + price: Money.from_amount(1), + operation_category: 'create', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + let(:request_xml) { <<-XML + + + + + + test.test + 10 + test + + + + + #{valid_legal_document} + + + + + XML + } + + it 'creates domain' do + expect { request }.to change { Domain.count }.from(0).to(1) + end + + specify 'expire_time' do + request + expire_time = (Time.zone.parse('05.07.2010 10:30') + 10.years + 1.day).beginning_of_day + expect(Domain.first.expire_time).to eq(expire_time) end specify do diff --git a/spec/requests/epp/domain/renew/default_period_spec.rb b/spec/requests/epp/domain/renew/default_period_spec.rb new file mode 100644 index 000000000..70ab2d58d --- /dev/null +++ b/spec/requests/epp/domain/renew/default_period_spec.rb @@ -0,0 +1,55 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:renew', settings: false do + let(:request) { post '/epp/command/renew', frame: request_xml } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:zone) { create(:zone, origin: 'test') } + let!(:registrar) { create(:registrar_with_unlimited_balance) } + let!(:price) { create(:price, + duration: '1 year', + price: Money.from_amount(1), + operation_category: 'renew', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + let!(:domain) { create(:domain, + registrar: registrar, + name: 'test.test', + expire_time: Time.zone.parse('05.07.2010')) + } + let(:request_xml) { <<-XML + + + + + + test.test + 2010-07-05 + 1 + + + + + XML + } + + before :example do + travel_to Time.zone.parse('05.07.2010') + Setting.days_to_renew_domain_before_expire = 0 + sign_in_to_epp_area(user: user) + end + + context 'when period is absent' do + it 'renews domain for 1 year' do + request + domain.reload + expect(domain.expire_time).to eq(Time.zone.parse('05.07.2011')) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end +end diff --git a/spec/requests/epp/domain/renew/period_spec.rb b/spec/requests/epp/domain/renew/period_spec.rb new file mode 100644 index 000000000..0a11161c6 --- /dev/null +++ b/spec/requests/epp/domain/renew/period_spec.rb @@ -0,0 +1,93 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:renew', settings: false do + let(:request) { post '/epp/command/renew', frame: request_xml } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:zone) { create(:zone, origin: 'test') } + let!(:registrar) { create(:registrar_with_unlimited_balance) } + let!(:domain) { create(:domain, + registrar: registrar, + name: 'test.test', + expire_time: Time.zone.parse('05.07.2010 10:30')) + } + + before :example do + travel_to Time.zone.parse('05.07.2010') + Setting.days_to_renew_domain_before_expire = 0 + sign_in_to_epp_area(user: user) + end + + context 'when period is 3 months' do + let!(:price) { create(:price, + duration: '3 months', + price: Money.from_amount(1), + operation_category: 'renew', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + let(:request_xml) { <<-XML + + + + + + test.test + 2010-07-05 + 3 + + + + + XML + } + + it 'renews domain for 3 months' do + request + domain.reload + expect(domain.expire_time).to eq(Time.zone.parse('05.10.2010 10:30')) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end + + context 'when period is 10 years' do + let!(:price) { create(:price, + duration: '10 years', + price: Money.from_amount(1), + operation_category: 'renew', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + let(:request_xml) { <<-XML + + + + + + test.test + 2010-07-05 + 10 + + + + + XML + } + + it 'renews domain for 10 years' do + request + domain.reload + expect(domain.expire_time).to eq(Time.zone.parse('05.07.2020 10:30')) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end +end diff --git a/spec/requests/epp/domain/renew/price_spec.rb b/spec/requests/epp/domain/renew/price_spec.rb new file mode 100644 index 000000000..3b5139103 --- /dev/null +++ b/spec/requests/epp/domain/renew/price_spec.rb @@ -0,0 +1,67 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:renew', settings: false do + let(:request) { post '/epp/command/renew', frame: request_xml } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:zone) { create(:zone, origin: 'test') } + let!(:registrar) { create(:registrar_with_unlimited_balance) } + let!(:domain) { create(:domain, + registrar: registrar, + name: 'test.test', + expire_time: Time.zone.parse('05.07.2010 10:30')) + } + let(:request_xml) { <<-XML + + + + + + test.test + 2010-07-05 + 1 + + + + + XML + } + + before :example do + travel_to Time.zone.parse('05.07.2010') + Setting.days_to_renew_domain_before_expire = 0 + sign_in_to_epp_area(user: user) + end + + context 'when price is present' do + let!(:price) { create(:price, + duration: '1 year', + price: Money.from_amount(1), + operation_category: 'renew', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + + it 'renews domain for 1 year' do + request + domain.reload + expect(domain.expire_time).to eq(Time.zone.parse('05.07.2011 10:30')) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end + + context 'when price is absent' do + it 'does not renew domain' do + expect { request; domain.reload }.to_not change { domain.expire_time } + end + + specify do + request + expect(response).to have_code_of(2104) + end + end +end