From 34c14e5befe949c6a28bef7098b64076b56eca96 Mon Sep 17 00:00:00 2001 From: Oleg Hasjanov Date: Thu, 8 Feb 2024 15:00:41 +0200 Subject: [PATCH] changed count of contact validations --- .../api/v1/registrant/contacts_controller.rb | 2 +- app/interactions/actions/email_check.rb | 16 ++++-- app/models/concerns/email_verifable.rb | 19 +++---- test/models/contact_test.rb | 53 +++++++++++++++++++ 4 files changed, 75 insertions(+), 15 deletions(-) diff --git a/app/controllers/api/v1/registrant/contacts_controller.rb b/app/controllers/api/v1/registrant/contacts_controller.rb index 9bc66d6eb..1c22277df 100644 --- a/app/controllers/api/v1/registrant/contacts_controller.rb +++ b/app/controllers/api/v1/registrant/contacts_controller.rb @@ -145,7 +145,7 @@ module Api contact.transaction do contact.save! - contact.validate_email_by_regex_and_mx + contact.validate_email_by_regex_and_mx(single_email: true) contact.remove_force_delete_for_valid_contact action = current_registrant_user.actions.create!(contact: contact, operation: :update) diff --git a/app/interactions/actions/email_check.rb b/app/interactions/actions/email_check.rb index b15e4bad2..433f4a476 100644 --- a/app/interactions/actions/email_check.rb +++ b/app/interactions/actions/email_check.rb @@ -1,18 +1,19 @@ module Actions class EmailCheck - attr_reader :email, :validation_eventable, :check_level + attr_reader :email, :validation_eventable, :check_level, :single_email SAVE_RESULTS_BATCH_SIZE = 500 - def initialize(email:, validation_eventable:, check_level: nil) + def initialize(email:, validation_eventable:, single_email: false, check_level: nil) @email = email @validation_eventable = validation_eventable @check_level = check_level || :mx + @single_email = single_email end def call result = check_email(email) - save_result(result) + single_email ? save_single_result(validation_eventable: validation_eventable, result: result) : save_result(result) handle_logging(result) result.success end @@ -48,6 +49,15 @@ module Actions contact.validation_events.destroy_all if success end + def save_single_result(validation_eventable:, result:) + handle_mx_validation(result) if !result.success && @check_level == 'mx' + result.configuration = nil + + handle_saving_result(validation_eventable, result) + rescue ActiveRecord::RecordNotSaved + logger.info "Cannot save validation result for #{log_object_id}" and return true + end + def save_result(result) contacts = Contact.where(email: email) diff --git a/app/models/concerns/email_verifable.rb b/app/models/concerns/email_verifable.rb index e2d55f299..ba436f5cb 100644 --- a/app/models/concerns/email_verifable.rb +++ b/app/models/concerns/email_verifable.rb @@ -5,16 +5,12 @@ module EmailVerifable scope :recently_not_validated, -> { where.not(id: ValidationEvent.validated_ids_by(name)) } end - def validate_email_by_regex_and_mx - # return if Rails.env.test? - - verify_email(check_level: 'regex') - verify_email(check_level: 'mx') + def validate_email_by_regex_and_mx(single_email: false) + verify_email(check_level: 'regex', single_email: single_email) + verify_email(check_level: 'mx', single_email: single_email) end def remove_force_delete_for_valid_contact - # return if Rails.env.test? - domains.each do |domain| contact_emails_valid?(domain) ? domain.cancel_force_delete : nil end @@ -68,14 +64,15 @@ module EmailVerifable process_error(:billing_email) unless result end - def verify_email(check_level: 'regex') - verify(email: email, check_level: check_level) + def verify_email(check_level: 'regex', single_email: false) + verify(email: email, check_level: check_level, single_email: single_email) end - def verify(email:, check_level: 'regex') + def verify(email:, check_level: 'regex', single_email: false) action = Actions::EmailCheck.new(email: email, validation_eventable: self, - check_level: check_level) + check_level: check_level, + single_email: single_email) action.call end diff --git a/test/models/contact_test.rb b/test/models/contact_test.rb index 31f171e1f..fb34ff9e3 100644 --- a/test/models/contact_test.rb +++ b/test/models/contact_test.rb @@ -375,6 +375,59 @@ class ContactTest < ActiveJob::TestCase # assert_not @contact.domains.first.force_delete_scheduled? # end + def test_should_be_validated_only_one_contact_with_same_email + trumail_results = OpenStruct.new(success: false, + email: @contact.email, + domain: 'box.tests', + errors: { mx: 'target host(s) not found' }) + + Spy.on_instance_method(Actions::EmailCheck, :check_email).and_return(trumail_results) + Spy.on_instance_method(Actions::AAndAaaaEmailValidation, :call).and_return([true]) + + contact_1 = contacts(:john) + contact_2 = contacts(:william) + + assert_equal contact_1.validation_events.count, 0 + assert_equal contact_2.validation_events.count, 0 + + contact_1.email = 'test@example.com' && contact_1.save! && contact_1.reload + contact_2.email = 'test@example.com' && contact_2.save! && contact_2.reload + + contact_1.validate_email_by_regex_and_mx(single_email: true) + + contact_1.reload && contact_2.reload + + assert_equal contact_1.validation_events.count, 1 + assert_equal contact_2.validation_events.count, 0 + end + + def test_should_be_validated_serial_contacts_with_same_email + trumail_results = OpenStruct.new(success: false, + email: @contact.email, + domain: 'box.tests', + errors: { mx: 'target host(s) not found' }) + + Spy.on_instance_method(Actions::EmailCheck, :check_email).and_return(trumail_results) + Spy.on_instance_method(Actions::AAndAaaaEmailValidation, :call).and_return([true]) + + contact_1 = contacts(:john) + contact_2 = contacts(:william) + + assert_equal contact_1.validation_events.count, 0 + assert_equal contact_2.validation_events.count, 0 + + contact_1.update_attribute(:email, 'tester@example.com') + contact_2.update_attribute(:email, 'tester@example.com') + contact_1.reload && contact_2.reload + + contact_1.validate_email_by_regex_and_mx(single_email: false) + + contact_1.reload && contact_2.reload + + assert_equal contact_1.validation_events.count, 1 + assert_equal contact_2.validation_events.count, 1 + end + private def make_contact_free_of_domains_where_it_acts_as_a_registrant(contact)