diff --git a/app/models/concerns/domain/force_delete.rb b/app/models/concerns/domain/force_delete.rb index 96f1a94b3..45f45dab6 100644 --- a/app/models/concerns/domain/force_delete.rb +++ b/app/models/concerns/domain/force_delete.rb @@ -1,30 +1,48 @@ module Concerns::Domain::ForceDelete extend ActiveSupport::Concern - included do - alias_attribute :force_delete_time, :force_delete_at - end - def force_delete_scheduled? statuses.include?(DomainStatus::FORCE_DELETE) end def schedule_force_delete - self.statuses_backup = statuses - statuses.delete(DomainStatus::CLIENT_DELETE_PROHIBITED) - statuses.delete(DomainStatus::SERVER_DELETE_PROHIBITED) + preserve_current_statuses_for_force_delete + add_force_delete_statuses + self.force_delete_at = (Time.zone.now + (Setting.redemption_grace_period.days + 1.day)).utc + .beginning_of_day + stop_all_pending_actions + allow_deletion + save(validate: false) + end + + def cancel_force_delete + raise 'Domain must be discarded before cancelling force delete procedure' unless discarded? + + restore_statuses_before_force_delete + remove_force_delete_statuses + self.force_delete_at = nil + save(validate: false) + end + + private + + def stop_all_pending_actions statuses.delete(DomainStatus::PENDING_UPDATE) statuses.delete(DomainStatus::PENDING_TRANSFER) statuses.delete(DomainStatus::PENDING_RENEW) statuses.delete(DomainStatus::PENDING_CREATE) + end - statuses.delete(DomainStatus::FORCE_DELETE) - statuses.delete(DomainStatus::SERVER_RENEW_PROHIBITED) - statuses.delete(DomainStatus::SERVER_TRANSFER_PROHIBITED) - statuses.delete(DomainStatus::SERVER_UPDATE_PROHIBITED) - statuses.delete(DomainStatus::SERVER_MANUAL_INZONE) - statuses.delete(DomainStatus::PENDING_DELETE) + def preserve_current_statuses_for_force_delete + self.statuses_before_force_delete = statuses + end + def restore_statuses_before_force_delete + self.statuses = statuses_before_force_delete + self.statuses_before_force_delete = nil + end + + def add_force_delete_statuses statuses << DomainStatus::FORCE_DELETE statuses << DomainStatus::SERVER_RENEW_PROHIBITED statuses << DomainStatus::SERVER_TRANSFER_PROHIBITED @@ -34,21 +52,19 @@ module Concerns::Domain::ForceDelete if (statuses & [DomainStatus::SERVER_HOLD, DomainStatus::CLIENT_HOLD]).empty? statuses << DomainStatus::SERVER_MANUAL_INZONE end - - self.force_delete_at = (Time.zone.now + (Setting.redemption_grace_period.days + 1.day)).utc.beginning_of_day unless force_delete_at - save!(validate: false) end - def cancel_force_delete - s = [] - s << DomainStatus::EXPIRED if statuses.include?(DomainStatus::EXPIRED) - s << DomainStatus::SERVER_HOLD if statuses.include?(DomainStatus::SERVER_HOLD) - s << DomainStatus::DELETE_CANDIDATE if statuses.include?(DomainStatus::DELETE_CANDIDATE) + def remove_force_delete_statuses + statuses.delete(DomainStatus::FORCE_DELETE) + statuses.delete(DomainStatus::SERVER_RENEW_PROHIBITED) + statuses.delete(DomainStatus::SERVER_TRANSFER_PROHIBITED) + statuses.delete(DomainStatus::SERVER_UPDATE_PROHIBITED) + statuses.delete(DomainStatus::PENDING_DELETE) + statuses.delete(DomainStatus::SERVER_MANUAL_INZONE) + end - self.statuses = (statuses_backup + s).uniq - - self.force_delete_at = nil - self.statuses_backup = [] - save(validate: false) + def allow_deletion + statuses.delete(DomainStatus::CLIENT_DELETE_PROHIBITED) + statuses.delete(DomainStatus::SERVER_DELETE_PROHIBITED) end end diff --git a/app/models/domain.rb b/app/models/domain.rb index 0ec5c67fd..855d98e12 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -577,6 +577,7 @@ class Domain < ActiveRecord::Base hash = super hash['auth_info'] = hash.delete('transfer_code') # API v1 requirement hash['valid_from'] = hash['registered_at'] # API v1 requirement + hash.delete('statuses_before_force_delete') hash end diff --git a/app/presenters/domain_presenter.rb b/app/presenters/domain_presenter.rb index 11d767203..30441ec7d 100644 --- a/app/presenters/domain_presenter.rb +++ b/app/presenters/domain_presenter.rb @@ -34,7 +34,7 @@ class DomainPresenter end def force_delete_date - view.l(domain.force_delete_time, format: :date) if domain.force_delete_time + view.l(domain.force_delete_at, format: :date) if domain.force_delete_at end def admin_contact_names diff --git a/app/views/admin/domains/partials/_general.html.erb b/app/views/admin/domains/partials/_general.html.erb index 7e09a7756..5be18eba4 100644 --- a/app/views/admin/domains/partials/_general.html.erb +++ b/app/views/admin/domains/partials/_general.html.erb @@ -31,8 +31,8 @@
<%= t('.delete_time') %>
<%= l(@domain.delete_at) %>
-
<%= t('.force_delete_time') %>
-
<%= l(@domain.force_delete_at) %>
+
<%= Domain.human_attribute_name :force_delete_at %>
+
<%= l @domain.force_delete_at %>
diff --git a/config/locales/admin/domains.en.yml b/config/locales/admin/domains.en.yml index da4c4f013..9ae02ba21 100644 --- a/config/locales/admin/domains.en.yml +++ b/config/locales/admin/domains.en.yml @@ -37,7 +37,6 @@ en: general: outzone_time: Outzone time delete_time: Delete time - force_delete_time: Force delete time admin_contacts: title: Admin. contacts diff --git a/db/migrate/20180422154642_rename_domains_statuses_backup_to_statuses_before_force_delete.rb b/db/migrate/20180422154642_rename_domains_statuses_backup_to_statuses_before_force_delete.rb new file mode 100644 index 000000000..a6784f02e --- /dev/null +++ b/db/migrate/20180422154642_rename_domains_statuses_backup_to_statuses_before_force_delete.rb @@ -0,0 +1,5 @@ +class RenameDomainsStatusesBackupToStatusesBeforeForceDelete < ActiveRecord::Migration + def change + rename_column :domains, :statuses_backup, :statuses_before_force_delete + end +end diff --git a/db/structure.sql b/db/structure.sql index b07f08000..3bd6939f6 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -909,7 +909,7 @@ CREATE TABLE public.domains ( statuses character varying[], reserved boolean DEFAULT false, status_notes public.hstore, - statuses_backup character varying[] DEFAULT '{}'::character varying[], + statuses_before_force_delete character varying[] DEFAULT '{}'::character varying[], upid integer, up_date timestamp without time zone, uuid uuid DEFAULT public.gen_random_uuid() NOT NULL @@ -4747,6 +4747,8 @@ INSERT INTO schema_migrations (version) VALUES ('20180327151906'); INSERT INTO schema_migrations (version) VALUES ('20180331200125'); +INSERT INTO schema_migrations (version) VALUES ('20180422154642'); + INSERT INTO schema_migrations (version) VALUES ('20180612042234'); INSERT INTO schema_migrations (version) VALUES ('20180612042625'); diff --git a/doc/repp/v1/domain.md b/doc/repp/v1/domain.md index adb9c4c8e..4c9476125 100644 --- a/doc/repp/v1/domain.md +++ b/doc/repp/v1/domain.md @@ -63,10 +63,7 @@ Content-Type: application/json ], "reserved": false, "status_notes": { - }, - "statuses_backup": [ - - ] + } } ], "total_number_of_records": 2 diff --git a/spec/models/concerns/domain/force_delete_spec.rb b/spec/models/concerns/domain/force_delete_spec.rb deleted file mode 100644 index cc022a6d7..000000000 --- a/spec/models/concerns/domain/force_delete_spec.rb +++ /dev/null @@ -1,102 +0,0 @@ -require 'rails_helper' - -RSpec.describe Domain do - it { is_expected.to alias_attribute(:force_delete_time, :force_delete_at) } - - before :example do - create(:zone, origin: 'ee') - end - - it 'should set force delete time' do - domain = build(:domain) - domain.nameservers.build(attributes_for(:nameserver)) - domain.nameservers.build(attributes_for(:nameserver)) - domain.save! - - domain.statuses = ['ok'] - domain.schedule_force_delete - - domain.statuses.should match_array([ - "serverForceDelete", - "pendingDelete", - "serverManualInzone", - "serverRenewProhibited", - "serverTransferProhibited", - "serverUpdateProhibited" - ]) - - domain.cancel_force_delete - - domain.statuses.should == ['ok'] - - domain.statuses = [ - DomainStatus::CLIENT_DELETE_PROHIBITED, - DomainStatus::SERVER_DELETE_PROHIBITED, - DomainStatus::PENDING_UPDATE, - DomainStatus::PENDING_TRANSFER, - DomainStatus::PENDING_RENEW, - DomainStatus::PENDING_CREATE, - DomainStatus::CLIENT_HOLD, - DomainStatus::EXPIRED, - DomainStatus::SERVER_HOLD, - DomainStatus::DELETE_CANDIDATE - ] - - domain.save - - domain.schedule_force_delete - - domain.statuses.should match_array([ - "clientHold", - "deleteCandidate", - "expired", - "serverForceDelete", - "pendingDelete", - "serverHold", - "serverRenewProhibited", - "serverTransferProhibited", - "serverUpdateProhibited" - ]) - - domain.cancel_force_delete - - domain.statuses.should match_array([ - "clientDeleteProhibited", - "clientHold", - "deleteCandidate", - "expired", - "pendingCreate", - "pendingRenew", - "pendingTransfer", - "pendingUpdate", - "serverDeleteProhibited", - "serverHold" - ]) - end - - it 'should should be manual in zone and held after force delete' do - domain = create(:domain) - Setting.redemption_grace_period = 1 - - domain.valid? - domain.outzone_at = Time.zone.now + 1.day # before redemption grace period - # what should this be? - # domain.server_holdable?.should be true - domain.statuses.include?(DomainStatus::SERVER_HOLD).should be false - domain.statuses.include?(DomainStatus::SERVER_MANUAL_INZONE).should be false - domain.schedule_force_delete - domain.server_holdable?.should be false - domain.statuses.include?(DomainStatus::SERVER_MANUAL_INZONE).should be true - domain.statuses.include?(DomainStatus::SERVER_HOLD).should be false - end - - it 'should not allow update after force delete' do - domain = create(:domain) - domain.valid? - domain.pending_update_prohibited?.should be false - domain.update_prohibited?.should be false - domain.schedule_force_delete - domain.pending_update_prohibited?.should be true - domain.update_prohibited?.should be true - end -end diff --git a/spec/presenters/domain_presenter_spec.rb b/spec/presenters/domain_presenter_spec.rb index d0cef5e6d..ff4fc2841 100644 --- a/spec/presenters/domain_presenter_spec.rb +++ b/spec/presenters/domain_presenter_spec.rb @@ -63,7 +63,7 @@ RSpec.describe DomainPresenter do subject(:force_delete_date) { presenter.force_delete_date } context 'when present' do - let(:domain) { instance_double(Domain, force_delete_time: '05.07.2010') } + let(:domain) { instance_double(Domain, force_delete_at: '05.07.2010') } it 'returns localized date' do expect(view).to receive(:l).with('05.07.2010', format: :date).and_return('delete date') @@ -72,7 +72,7 @@ RSpec.describe DomainPresenter do end context 'when absent' do - let(:domain) { instance_double(Domain, force_delete_time: nil) } + let(:domain) { instance_double(Domain, force_delete_at: nil) } specify { expect(force_delete_date).to be_nil } end diff --git a/test/integration/admin/domains/force_delete_test.rb b/test/integration/admin/domains/force_delete_test.rb index 3e5d7d4d6..d48444fb9 100644 --- a/test/integration/admin/domains/force_delete_test.rb +++ b/test/integration/admin/domains/force_delete_test.rb @@ -44,8 +44,8 @@ class AdminAreaDomainForceDeleteTest < ActionDispatch::IntegrationTest end def test_cancels_scheduled_domain_force_delete - @domain.update_attribute(:statuses, [DomainStatus::FORCE_DELETE]) - assert @domain.force_delete_scheduled? + @domain.discard + @domain.schedule_force_delete visit edit_admin_domain_url(@domain) click_link_or_button 'Cancel force delete' diff --git a/test/models/domain/force_delete_test.rb b/test/models/domain/force_delete_test.rb new file mode 100644 index 000000000..535ad84d8 --- /dev/null +++ b/test/models/domain/force_delete_test.rb @@ -0,0 +1,129 @@ +require 'test_helper' + +class DomainForceDeleteTest < ActiveSupport::TestCase + def setup + @domain = domains(:shop) + end + + def test_schedule_force_delete + @original_redemption_grace_period = Setting.redemption_grace_period + Setting.redemption_grace_period = 30 + travel_to Time.zone.parse('2010-07-05 00:00') + + @domain.schedule_force_delete + @domain.reload + + assert @domain.force_delete_scheduled? + assert_equal Time.zone.parse('2010-08-04 03:00'), @domain.force_delete_at + + travel_back + Setting.redemption_grace_period = @original_redemption_grace_period + end + + def test_scheduling_force_delete_adds_corresponding_statuses + statuses_to_be_added = [ + DomainStatus::FORCE_DELETE, + DomainStatus::SERVER_RENEW_PROHIBITED, + DomainStatus::SERVER_TRANSFER_PROHIBITED, + DomainStatus::SERVER_UPDATE_PROHIBITED, + DomainStatus::PENDING_DELETE, + ] + + @domain.schedule_force_delete + @domain.reload + assert (@domain.statuses & statuses_to_be_added) == statuses_to_be_added + end + + def test_scheduling_force_delete_allows_domain_deletion + statuses_to_be_removed = [ + DomainStatus::CLIENT_DELETE_PROHIBITED, + DomainStatus::SERVER_DELETE_PROHIBITED, + ] + + @domain.statuses = statuses_to_be_removed + %w[other-status] + @domain.schedule_force_delete + @domain.reload + assert_empty @domain.statuses & statuses_to_be_removed + end + + def test_scheduling_force_delete_stops_pending_actions + statuses_to_be_removed = [ + DomainStatus::PENDING_UPDATE, + DomainStatus::PENDING_TRANSFER, + DomainStatus::PENDING_RENEW, + DomainStatus::PENDING_CREATE, + ] + + @domain.statuses = statuses_to_be_removed + %w[other-status] + @domain.schedule_force_delete + @domain.reload + assert_empty @domain.statuses & statuses_to_be_removed, 'Pending actions should be stopped' + end + + def test_scheduling_force_delete_preserves_current_statuses + @domain.statuses = %w[test1 test2] + @domain.schedule_force_delete + @domain.reload + assert_equal %w[test1 test2], @domain.statuses_before_force_delete + end + + def test_scheduling_force_delete_bypasses_validation + @domain = domains(:invalid) + @domain.schedule_force_delete + assert @domain.force_delete_scheduled? + end + + def test_cancelling_force_delete_on_a_discarded_domain + @domain.discard + @domain.schedule_force_delete + @domain.cancel_force_delete + @domain.reload + assert_not @domain.force_delete_scheduled? + assert_nil @domain.force_delete_at + end + + def test_cancelling_force_delete_requires_a_domain_to_be_discarded + @domain.schedule_force_delete + assert_raises StandardError do + @domain.cancel_force_delete + end + end + + def test_cancelling_force_delete_bypasses_validation + @domain = domains(:invalid) + @domain.discard + @domain.schedule_force_delete + @domain.cancel_force_delete + assert_not @domain.force_delete_scheduled? + end + + def test_cancelling_force_delete_removes_statuses_that_were_set_on_force_delete + statuses = [ + DomainStatus::FORCE_DELETE, + DomainStatus::SERVER_RENEW_PROHIBITED, + DomainStatus::SERVER_TRANSFER_PROHIBITED, + DomainStatus::SERVER_UPDATE_PROHIBITED, + DomainStatus::PENDING_DELETE, + DomainStatus::SERVER_MANUAL_INZONE + ] + @domain.discard + @domain.statuses = @domain.statuses + statuses + @domain.schedule_force_delete + + @domain.cancel_force_delete + @domain.reload + + assert_empty @domain.statuses & statuses + end + + def test_cancelling_force_delete_restores_statuses_that_a_domain_had_before_force_delete + @domain.discard + @domain.statuses_before_force_delete = ['test1', DomainStatus::DELETE_CANDIDATE] + + @domain.cancel_force_delete + @domain.reload + + assert_equal ['test1', DomainStatus::DELETE_CANDIDATE], @domain.statuses + assert_nil @domain.statuses_before_force_delete + end +end diff --git a/test/support/rails5_assetions.rb b/test/support/rails5_assertions.rb similarity index 100% rename from test/support/rails5_assetions.rb rename to test/support/rails5_assertions.rb diff --git a/test/test_helper.rb b/test/test_helper.rb index 500861f75..56a4a7aeb 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -11,7 +11,7 @@ require 'minitest/mock' require 'capybara/rails' require 'capybara/minitest' require 'webmock/minitest' -require 'support/rails5_assetions' # Remove once upgraded to Rails 5 +require 'support/rails5_assertions' # Remove once upgraded to Rails 5 require 'application_system_test_case'