diff --git a/app/interactions/domains/cancel_force_delete/remove_force_delete_statuses.rb b/app/interactions/domains/cancel_force_delete/remove_force_delete_statuses.rb index c77820ecf..adb310e51 100644 --- a/app/interactions/domains/cancel_force_delete/remove_force_delete_statuses.rb +++ b/app/interactions/domains/cancel_force_delete/remove_force_delete_statuses.rb @@ -2,10 +2,12 @@ module Domains module CancelForceDelete class RemoveForceDeleteStatuses < Base def execute - domain.statuses.delete(DomainStatus::FORCE_DELETE) - domain.statuses.delete(DomainStatus::SERVER_RENEW_PROHIBITED) - domain.statuses.delete(DomainStatus::SERVER_TRANSFER_PROHIBITED) - domain.statuses.delete(DomainStatus::CLIENT_HOLD) + domain_statuses = [DomainStatus::FORCE_DELETE, + DomainStatus::SERVER_RENEW_PROHIBITED, + DomainStatus::SERVER_TRANSFER_PROHIBITED, + DomainStatus::CLIENT_HOLD] + rejected_statuses = domain.statuses.reject { |a| domain_statuses.include? a } + domain.statuses = rejected_statuses domain.save(validate: false) end end diff --git a/app/interactions/domains/cancel_force_delete/restore_statuses_before_force_delete.rb b/app/interactions/domains/cancel_force_delete/restore_statuses_before_force_delete.rb index c55c06764..4643a8bea 100644 --- a/app/interactions/domains/cancel_force_delete/restore_statuses_before_force_delete.rb +++ b/app/interactions/domains/cancel_force_delete/restore_statuses_before_force_delete.rb @@ -2,8 +2,10 @@ module Domains module CancelForceDelete class RestoreStatusesBeforeForceDelete < Base def execute - domain.statuses = domain.statuses_before_force_delete + # domain.statuses = domain.statuses_before_force_delete + domain.statuses = domain.force_delete_domain_statuses_history || [] domain.statuses_before_force_delete = nil + domain.force_delete_domain_statuses_history = nil domain.save(validate: false) end end diff --git a/app/interactions/domains/force_delete/prepare_domain.rb b/app/interactions/domains/force_delete/prepare_domain.rb index 74eea21ed..e45f7969c 100644 --- a/app/interactions/domains/force_delete/prepare_domain.rb +++ b/app/interactions/domains/force_delete/prepare_domain.rb @@ -6,6 +6,7 @@ module Domains DomainStatus::SERVER_TRANSFER_PROHIBITED].freeze def execute + domain.force_delete_domain_statuses_history = domain.statuses domain.statuses_before_force_delete = domain.statuses domain.statuses |= STATUSES_TO_SET domain.save(validate: false) diff --git a/app/models/concerns/domain/force_delete.rb b/app/models/concerns/domain/force_delete.rb index bc89022d0..b514675c1 100644 --- a/app/models/concerns/domain/force_delete.rb +++ b/app/models/concerns/domain/force_delete.rb @@ -1,6 +1,10 @@ module Domain::ForceDelete # rubocop:disable Metrics/ModuleLength extend ActiveSupport::Concern + FORCE_DELETE_STATUSES = [DomainStatus::FORCE_DELETE, + DomainStatus::SERVER_RENEW_PROHIBITED, + DomainStatus::SERVER_TRANSFER_PROHIBITED].freeze + included do store_accessor :force_delete_data, :force_delete_type, @@ -52,6 +56,7 @@ module Domain::ForceDelete # rubocop:disable Metrics/ModuleLength def cancel_force_delete Domains::CancelForceDelete::CancelForceDelete.run(domain: self) + # self.statuses = force_delete_domain_statuses_history end def outzone_date diff --git a/app/models/concerns/domain/registry_lockable.rb b/app/models/concerns/domain/registry_lockable.rb index 2c0f5c0fe..4f9340aaf 100644 --- a/app/models/concerns/domain/registry_lockable.rb +++ b/app/models/concerns/domain/registry_lockable.rb @@ -36,9 +36,10 @@ module Domain::RegistryLockable transaction do LOCK_STATUSES.each do |domain_status| - statuses.delete(domain_status) + statuses.delete([domain_status]) end self.locked_by_registrant_at = nil + self.statuses = admin_store_statuses_history || [] alert_registrar_lock_changes!(lock: false) save! diff --git a/app/models/domain.rb b/app/models/domain.rb index 91b91584f..04491bc53 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -12,10 +12,18 @@ class Domain < ApplicationRecord include Domain::Disputable include Domain::BulkUpdatable + LOCK_STATUSES = [DomainStatus::SERVER_UPDATE_PROHIBITED, + DomainStatus::SERVER_DELETE_PROHIBITED, + DomainStatus::SERVER_TRANSFER_PROHIBITED].freeze + attr_accessor :roles attr_accessor :legal_document_id + store_accessor :json_statuses_history, + :force_delete_domain_statuses_history, + :admin_store_statuses_history + alias_attribute :on_hold_time, :outzone_at alias_attribute :outzone_time, :outzone_at alias_attribute :auth_info, :transfer_code # Old attribute name; for PaperTrail @@ -551,8 +559,23 @@ class Domain < ApplicationRecord statuses.include?(DomainStatus::FORCE_DELETE) end + def update_unless_locked_by_registrant(update) + update(admin_store_statuses_history: update) unless locked_by_registrant? + end + + def update_not_by_locked_statuses(update) + return unless locked_by_registrant? + + result = update.reject { |status| LOCK_STATUSES.include? status } + update(admin_store_statuses_history: result) + end + # special handling for admin changing status def admin_status_update(update) + update_unless_locked_by_registrant(update) + + update_not_by_locked_statuses(update) + # check for deleted status statuses.each do |s| unless update.include? s diff --git a/db/data/20210406083149_transfer_domain_statuses_before_force_delete_to_json_history.rb b/db/data/20210406083149_transfer_domain_statuses_before_force_delete_to_json_history.rb new file mode 100644 index 000000000..9aacf03a8 --- /dev/null +++ b/db/data/20210406083149_transfer_domain_statuses_before_force_delete_to_json_history.rb @@ -0,0 +1,13 @@ +class TransferDomainStatusesBeforeForceDeleteToJsonHistory < ActiveRecord::Migration[6.0] + def up + domains = Domain.where.not(statuses_before_force_delete: nil) + domains.each do |domain| + domain.force_delete_domain_statuses_history = domain.statuses_before_force_delete + domain.save + end + end + + def down + # raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/data/20210407140317_transfer_data_from_domain_statuses_to_admin_status_history.rb b/db/data/20210407140317_transfer_data_from_domain_statuses_to_admin_status_history.rb new file mode 100644 index 000000000..f1c390a61 --- /dev/null +++ b/db/data/20210407140317_transfer_data_from_domain_statuses_to_admin_status_history.rb @@ -0,0 +1,13 @@ +class TransferDataFromDomainStatusesToAdminStatusHistory < ActiveRecord::Migration[6.0] + def up + domains = Domain.all.select { |d| !d.locked_by_registrant?} + domains.each do |domain| + domain.admin_store_statuses_history = domain.statuses + domain.save + end + end + + def down + # raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/data_schema.rb b/db/data_schema.rb index 84cdf8411..15f126bd9 100644 --- a/db/data_schema.rb +++ b/db/data_schema.rb @@ -1,2 +1,2 @@ # encoding: UTF-8 -DataMigrate::Data.define(version: 20201007104651) +DataMigrate::Data.define(version: 20210407140317) diff --git a/db/migrate/20210405100631_add_json_statuses_history_field_to_domain.rb b/db/migrate/20210405100631_add_json_statuses_history_field_to_domain.rb new file mode 100644 index 000000000..de33223dc --- /dev/null +++ b/db/migrate/20210405100631_add_json_statuses_history_field_to_domain.rb @@ -0,0 +1,6 @@ +class AddJsonStatusesHistoryFieldToDomain < ActiveRecord::Migration[6.0] + def change + add_column :domains, :json_statuses_history, :jsonb + add_index :domains, :json_statuses_history, using: :gin + end +end diff --git a/db/structure.sql b/db/structure.sql index a28f7fabd..cac8a05df 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -843,7 +843,8 @@ CREATE TABLE public.domains ( uuid uuid DEFAULT public.gen_random_uuid() NOT NULL, locked_by_registrant_at timestamp without time zone, force_delete_start timestamp without time zone, - force_delete_data public.hstore + force_delete_data public.hstore, + json_statuses_history jsonb ); @@ -4124,6 +4125,17 @@ CREATE INDEX index_domain_transfers_on_domain_id ON public.domain_transfers USIN CREATE INDEX index_domains_on_delete_date ON public.domains USING btree (delete_date); + +-- Name: index_domains_on_json_statuses_history; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_domains_on_json_statuses_history ON public.domains USING gin (json_statuses_history); + + +-- +-- Name: index_domains_on_name; Type: INDEX; Schema: public; Owner: - + + -- -- Name: index_domains_on_name; Type: INDEX; Schema: public; Owner: -; Tablespace: -- @@ -5301,4 +5313,5 @@ INSERT INTO "schema_migrations" (version) VALUES ('20200916125326'), ('20200917104213'), ('20210215101019'), -('20200921084356'); +('20200921084356'), +('20210405100631'); diff --git a/test/models/domain/force_delete_test.rb b/test/models/domain/force_delete_test.rb index de28962ec..8eb45029b 100644 --- a/test/models/domain/force_delete_test.rb +++ b/test/models/domain/force_delete_test.rb @@ -12,6 +12,29 @@ class ForceDeleteTest < ActionMailer::TestCase Truemail.configure.default_validation_type = @old_validation_type end + def test_restore_domain_statuses_after_soft_force_delete + @domain.update(statuses: [DomainStatus::SERVER_RENEW_PROHIBITED]) + @domain.schedule_force_delete(type: :soft) + + assert @domain.force_delete_scheduled? + + assert @domain.force_delete_domain_statuses_history.include? DomainStatus::SERVER_RENEW_PROHIBITED + + @domain.cancel_force_delete + assert @domain.statuses.include? DomainStatus::SERVER_RENEW_PROHIBITED + end + + def test_clear_force_delete_domain_statuses_history + @domain.update(statuses: [DomainStatus::SERVER_RENEW_PROHIBITED]) + @domain.schedule_force_delete(type: :soft) + + assert @domain.force_delete_scheduled? + assert @domain.force_delete_domain_statuses_history.include? DomainStatus::SERVER_RENEW_PROHIBITED + @domain.cancel_force_delete + + assert_nil @domain.force_delete_domain_statuses_history + end + def test_schedules_force_delete_fast_track assert_not @domain.force_delete_scheduled? travel_to Time.zone.parse('2010-07-05') diff --git a/test/models/domain/registry_lockable_test.rb b/test/models/domain/registry_lockable_test.rb index 6e4a1826c..82770d0eb 100644 --- a/test/models/domain/registry_lockable_test.rb +++ b/test/models/domain/registry_lockable_test.rb @@ -3,7 +3,6 @@ require 'test_helper' class DomainRegistryLockableTest < ActiveSupport::TestCase def setup super - @domain = domains(:airport) end @@ -33,6 +32,56 @@ class DomainRegistryLockableTest < ActiveSupport::TestCase assert_not(@domain.locked_by_registrant?) end + def test_remove_lockalable_statuses_after_admin_intervention + @domain.apply_registry_lock + assert @domain.locked_by_registrant? + assert_equal @domain.statuses.sort, Domain::RegistryLockable::LOCK_STATUSES.sort + + deleted_status = @domain.statuses - [DomainStatus::SERVER_DELETE_PROHIBITED] + @domain.update(statuses: deleted_status) + assert_not @domain.locked_by_registrant? + + @domain.apply_registry_lock + assert @domain.locked_by_registrant? + @domain.remove_registry_lock + + assert_not @domain.statuses.include? DomainStatus::SERVER_UPDATE_PROHIBITED + assert_not @domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED + assert_not @domain.statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED + end + + def test_restore_domain_statuses_after_unlock + @domain.statuses = [DomainStatus::SERVER_UPDATE_PROHIBITED] + @domain.admin_store_statuses_history = [DomainStatus::SERVER_UPDATE_PROHIBITED] + @domain.save + assert @domain.admin_store_statuses_history.include? DomainStatus::SERVER_UPDATE_PROHIBITED + + @domain.apply_registry_lock + assert @domain.locked_by_registrant? + assert_equal @domain.statuses.sort, Domain::RegistryLockable::LOCK_STATUSES.sort + + @domain.remove_registry_lock + assert @domain.statuses.include? DomainStatus::SERVER_UPDATE_PROHIBITED + assert_not @domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED + assert_not @domain.statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED + end + + def test_add_additinal_status_for_locked_domain + @domain.apply_registry_lock + assert @domain.locked_by_registrant? + assert_equal @domain.statuses.sort, Domain::RegistryLockable::LOCK_STATUSES.sort + + @domain.statuses += [DomainStatus::SERVER_RENEW_PROHIBITED] + @domain.admin_store_statuses_history = [DomainStatus::SERVER_RENEW_PROHIBITED] + @domain.save + + @domain.remove_registry_lock + assert @domain.statuses.include? DomainStatus::SERVER_RENEW_PROHIBITED + assert_not @domain.statuses.include? DomainStatus::SERVER_UPDATE_PROHIBITED + assert_not @domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED + assert_not @domain.statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED + end + def test_registry_lock_on_lockable_domain refute(@domain.locked_by_registrant?) @domain.apply_registry_lock diff --git a/test/models/domain_test.rb b/test/models/domain_test.rb index 15ab8b0c2..2fdb916ad 100644 --- a/test/models/domain_test.rb +++ b/test/models/domain_test.rb @@ -27,6 +27,16 @@ class DomainTest < ActiveSupport::TestCase assert domains(:invalid).invalid? end + def test_valid_domain_statuses_history + @domain.force_delete_domain_statuses_history = [DomainStatus::SERVER_UPDATE_PROHIBITED, DomainStatus::SERVER_TRANSFER_PROHIBITED] + @domain.admin_store_statuses_history = [DomainStatus::SERVER_UPDATE_PROHIBITED] + assert @domain.valid? + + assert @domain.json_statuses_history['force_delete_domain_statuses_history'].include? 'serverUpdateProhibited' + assert @domain.json_statuses_history['force_delete_domain_statuses_history'].include? 'serverTransferProhibited' + assert_equal @domain.json_statuses_history['admin_store_statuses_history'], ['serverUpdateProhibited'] + end + # https://www.internet.ee/domeenid/ee-domeenireeglid#domeeninimede-registreerimine def test_validates_name_format assert_equal dns_zones(:one).origin, 'test'