diff --git a/app/interactions/actions/email_check.rb b/app/interactions/actions/email_check.rb index 483bf194b..bfd721d96 100644 --- a/app/interactions/actions/email_check.rb +++ b/app/interactions/actions/email_check.rb @@ -19,7 +19,11 @@ module Actions private def check_email(parsed_email) - Truemail.validate(parsed_email, with: check_level.to_sym).result + Truemail.validate(parsed_email, with: calculate_check_level).result + end + + def calculate_check_level + Rails.env.test? && check_level == 'smtp' ? :mx : check_level.to_sym end def save_result(result) diff --git a/app/interactions/domains/force_delete_lift/base.rb b/app/interactions/domains/force_delete_lift/base.rb index 535f149e6..196d7dd26 100644 --- a/app/interactions/domains/force_delete_lift/base.rb +++ b/app/interactions/domains/force_delete_lift/base.rb @@ -27,8 +27,8 @@ module Domains end def contact_emails_valid?(domain) - domain.contacts.all? { |contact| contact.email_verification.verified? } && - domain.registrant.email_verification.verified? + domain.contacts.all(&:need_to_lift_force_delete?) && + domain.registrant.need_to_lift_force_delete? end def bounces_absent?(domain) diff --git a/app/models/concerns/email_verifable.rb b/app/models/concerns/email_verifable.rb index 8509a3fc9..02bd8daef 100644 --- a/app/models/concerns/email_verifable.rb +++ b/app/models/concerns/email_verifable.rb @@ -6,30 +6,26 @@ module EmailVerifable end def email_verification_failed? - email_validations_present?(valid: false) + need_to_start_force_delete? end - def email_validations_present?(valid: true) - base_scope = valid ? recent_email_validations : recent_failed_email_validations - check_levels = ValidationEvent::VALID_CHECK_LEVELS - event_count_sum = 0 - check_levels.each do |level| - event_count = base_scope.select { |event| event.check_level == level }.count - event_count_sum += event_count + def need_to_start_force_delete? + ValidationEvent::INVALID_EVENTS_COUNT_BY_LEVEL.any? do |level, count| + validation_events.recent.order(id: :desc).limit(count).all? do |event| + event.check_level == level.to_s && event.failed? + end end - - event_count_sum > ValidationEvent::VALID_EVENTS_COUNT_THRESHOLD end - def recent_email_validations - validation_events.email_validation_event_type.successful.recent + def need_to_lift_force_delete? + validation_events.recent.failed.empty? || + ValidationEvent::REDEEM_EVENTS_COUNT_BY_LEVEL.any? do |level, count| + validation_events.recent.order(id: :desc).limit(count).all? do |event| + event.check_level == level.to_s && event.successful? + end + end end - def recent_failed_email_validations - validation_events.email_validation_event_type.failed.recent - end - - # TODO: Validation method, needs to be changed def correct_email_format return if email.blank? @@ -37,7 +33,6 @@ module EmailVerifable process_error(:email) unless result end - # TODO: Validation method, needs to be changed def correct_billing_email_format return if email.blank? @@ -45,6 +40,10 @@ module EmailVerifable process_error(:billing_email) unless result end + def verify_email(check_level: 'regex') + verify(email: email, check_level: check_level) + end + def verify(email:, check_level: 'regex') action = Actions::EmailCheck.new(email: email, validation_eventable: self, diff --git a/app/models/validation_event.rb b/app/models/validation_event.rb index 759f61d55..9237e12ab 100644 --- a/app/models/validation_event.rb +++ b/app/models/validation_event.rb @@ -10,6 +10,18 @@ class ValidationEvent < ApplicationRecord VALID_CHECK_LEVELS = %w[regex mx smtp].freeze VALID_EVENTS_COUNT_THRESHOLD = 5 + INVALID_EVENTS_COUNT_BY_LEVEL = { + regex: 1, + mx: 5, + smtp: 1, + }.freeze + + REDEEM_EVENTS_COUNT_BY_LEVEL = { + regex: 1, + mx: 1, + smtp: 1, + }.freeze + store_accessor :event_data, :errors, :check_level, :email belongs_to :validation_eventable, polymorphic: true @@ -17,13 +29,45 @@ class ValidationEvent < ApplicationRecord scope :recent, -> { where('created_at > ?', VALIDATION_PERIOD) } scope :successful, -> { where(success: true) } scope :failed, -> { where(success: false) } + scope :regex, -> { where('event_data @> ?', { 'check_level': 'regex' }.to_json) } + scope :mx, -> { where('event_data @> ?', { 'check_level': 'mx' }.to_json) } + scope :smtp, -> { where('event_data @> ?', { 'check_level': 'smtp' }.to_json) } + scope :by_object, ->(object) { where(validation_eventable: object) } + + after_create :check_for_force_delete def self.validated_ids_by(klass) recent.successful.where('validation_eventable_type = ?', klass) .pluck(:validation_eventable_id) end - def event_type - @event_type ||= ValidationEvent::EventType.new(self[:event_kind]) + def failed? + !success end + + def successful? + success + end + + def event_type + @event_type ||= ValidationEvent::EventType.new(self[:event_type]) + end + + def object + validation_eventable + end + + def check_for_force_delete + if object.need_to_start_force_delete? + start_force_delete + elsif object.need_to_lift_force_delete? + lift_force_delete + end + end + + def start_force_delete + Domains::ForceDeleteEmail::Base.run(email: email) + end + + def lift_force_delete; end end diff --git a/test/models/domain/force_delete_test.rb b/test/models/domain/force_delete_test.rb index 73a6245de..046fbaecb 100644 --- a/test/models/domain/force_delete_test.rb +++ b/test/models/domain/force_delete_test.rb @@ -393,7 +393,10 @@ class ForceDeleteTest < ActionMailer::TestCase contact = @domain.admin_contacts.first contact.update_attribute(:email, email) - contact.email_verification.verify + + ValidationEvent::VALID_EVENTS_COUNT_THRESHOLD.times do + contact.verify_email + end assert contact.email_verification_failed? @@ -414,20 +417,18 @@ class ForceDeleteTest < ActionMailer::TestCase travel_to Time.zone.parse('2010-07-05') email_one = '`@internet.ee' email_two = '@@internet.ee' - asserted_text_one = "Invalid email: #{email_one}" - asserted_text_two = "Invalid email: #{email_two}" contact_one = @domain.admin_contacts.first contact_one.update_attribute(:email, email_one) - contact_one.email_verification.verify + contact_one.verify_email - assert contact_one.email_verification_failed? + assert contact_one.need_to_start_force_delete? contact_two = @domain.admin_contacts.first contact_two.update_attribute(:email, email_two) - contact_two.email_verification.verify + contact_two.verify_email - assert contact_one.email_verification_failed? + assert contact_two.need_to_start_force_delete? @domain.reload @@ -449,7 +450,7 @@ class ForceDeleteTest < ActionMailer::TestCase contact = @domain.admin_contacts.first contact.update_attribute(:email, email) - contact.email_verification.verify + contact.verify_email assert contact.email_verification_failed? @@ -457,7 +458,11 @@ class ForceDeleteTest < ActionMailer::TestCase assert @domain.force_delete_scheduled? contact.update_attribute(:email, 'aaa@bbb.com') - contact.email_verification.verify + contact.reload + contact.verify_email + + assert contact.need_to_lift_force_delete? + refute contact.need_to_start_force_delete? assert_not contact.email_verification_failed? CheckForceDeleteLift.perform_now @@ -486,8 +491,8 @@ class ForceDeleteTest < ActionMailer::TestCase assert notification.text.include? asserted_text @domain.registrant.update(email: 'aaa@bbb.com') - @domain.registrant.email_verification.verify - assert_not @domain.registrant.email_verification_failed? + @domain.registrant.verify_email + assert @domain.registrant.need_to_lift_force_delete? CheckForceDeleteLift.perform_now @domain.reload diff --git a/test/models/validation_event_test.rb b/test/models/validation_event_test.rb new file mode 100644 index 000000000..ccee49c81 --- /dev/null +++ b/test/models/validation_event_test.rb @@ -0,0 +1,107 @@ +require 'test_helper' + +class ValidationEventTest < ActiveSupport::TestCase + + setup do + @domain = domains(:shop) + Setting.redemption_grace_period = 30 + ActionMailer::Base.deliveries.clear + end + + teardown do + + end + + def test_if_fd_need_to_be_set_if_invalid_email + @domain.update(valid_to: Time.zone.parse('2012-08-05')) + assert_not @domain.force_delete_scheduled? + travel_to Time.zone.parse('2010-07-05') + email = 'some@strangesentence@internet.ee' + + contact = @domain.admin_contacts.first + contact.update_attribute(:email, email) + contact.verify_email + contact.reload + + refute contact.validation_events.last.success? + assert contact.need_to_start_force_delete? + end + + def test_if_fd_need_to_be_lifted_if_email_fixed + test_if_fd_need_to_be_set_if_invalid_email + + email = 'email@internet.ee' + + contact = @domain.admin_contacts.first + contact.update_attribute(:email, email) + + contact.verify_email + contact.reload + + assert contact.need_to_lift_force_delete? + assert contact.validation_events.last.success? + end + + def test_if_fd_need_to_be_set_if_invalid_mx + @domain.update(valid_to: Time.zone.parse('2012-08-05')) + assert_not @domain.force_delete_scheduled? + travel_to Time.zone.parse('2010-07-05') + + email = 'email@somestrangedomain12345.ee' + contact = @domain.admin_contacts.first + contact.update_attribute(:email, email) + ValidationEvent::VALID_EVENTS_COUNT_THRESHOLD.times do + contact.verify_email(check_level: 'mx') + end + contact.reload + + refute contact.validation_events.limit(ValidationEvent::VALID_EVENTS_COUNT_THRESHOLD) + .any?(&:success?) + assert contact.need_to_start_force_delete? + end + + def test_if_fd_need_to_be_lifted_if_mx_fixed + test_if_fd_need_to_be_set_if_invalid_mx + + email = 'email@internet.ee' + contact = @domain.admin_contacts.first + contact.update_attribute(:email, email) + contact.verify_email(check_level: 'mx') + + contact.reload + assert contact.need_to_lift_force_delete? + assert contact.validation_events.last.success? + end + + def test_if_fd_need_to_be_set_if_invalid_smtp + @domain.update(valid_to: Time.zone.parse('2012-08-05')) + assert_not @domain.force_delete_scheduled? + travel_to Time.zone.parse('2010-07-05') + + email = 'email@somestrangedomain12345.ee' + contact = @domain.admin_contacts.first + contact.update_attribute(:email, email) + ValidationEvent::VALID_EVENTS_COUNT_THRESHOLD.times do + contact.verify_email(check_level: 'smtp') + end + contact.reload + + refute contact.validation_events.limit(ValidationEvent::VALID_EVENTS_COUNT_THRESHOLD) + .any?(&:success?) + assert contact.need_to_start_force_delete? + end + + def test_if_fd_need_to_be_lifted_if_smtp_fixed + test_if_fd_need_to_be_set_if_invalid_smtp + + email = 'valid@internet.ee' + contact = @domain.admin_contacts.first + contact.update_attribute(:email, email) + contact.verify_email(check_level: 'smtp') + + contact.reload + assert contact.need_to_lift_force_delete? + assert contact.validation_events.last.success? + end + +end