mirror of
https://github.com/internetee/registry.git
synced 2025-08-11 12:09:34 +02:00
Merge pull request #2647 from internetee/change-count-of-validation-contacts
changed count of contact validations
This commit is contained in:
commit
6c9ce3a7a1
8 changed files with 133 additions and 31 deletions
|
@ -145,7 +145,7 @@ module Api
|
||||||
contact.transaction do
|
contact.transaction do
|
||||||
contact.save!
|
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
|
contact.remove_force_delete_for_valid_contact
|
||||||
|
|
||||||
action = current_registrant_user.actions.create!(contact: contact, operation: :update)
|
action = current_registrant_user.actions.create!(contact: contact, operation: :update)
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
module Actions
|
module Actions
|
||||||
class ContactCreate
|
class ContactCreate
|
||||||
attr_reader :contact, :legal_document, :ident
|
attr_reader :contact, :legal_document, :ident, :result
|
||||||
|
|
||||||
def initialize(contact, legal_document, ident)
|
def initialize(contact, legal_document, ident)
|
||||||
@contact = contact
|
@contact = contact
|
||||||
@legal_document = legal_document
|
@legal_document = legal_document
|
||||||
@ident = ident
|
@ident = ident
|
||||||
|
@result = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
|
@ -14,19 +15,15 @@ module Actions
|
||||||
validate_ident
|
validate_ident
|
||||||
maybe_change_email
|
maybe_change_email
|
||||||
commit
|
commit
|
||||||
|
validate_contact
|
||||||
end
|
end
|
||||||
|
|
||||||
def maybe_change_email
|
def maybe_change_email
|
||||||
return if Rails.env.test?
|
return if Rails.env.test?
|
||||||
|
|
||||||
%i[regex mx].each do |m|
|
%i[regex mx].each do |m|
|
||||||
result = Actions::SimpleMailValidator.run(email: contact.email, level: m)
|
@result = Actions::SimpleMailValidator.run(email: contact.email, level: m)
|
||||||
if result
|
next if @result
|
||||||
@contact.validate_email_by_regex_and_mx
|
|
||||||
@contact.remove_force_delete_for_valid_contact
|
|
||||||
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
err_text = "email '#{contact.email}' didn't pass validation"
|
err_text = "email '#{contact.email}' didn't pass validation"
|
||||||
contact.add_epp_error('2005', nil, nil, "#{I18n.t(:parameter_value_syntax_error)} #{err_text}")
|
contact.add_epp_error('2005', nil, nil, "#{I18n.t(:parameter_value_syntax_error)} #{err_text}")
|
||||||
|
@ -92,5 +89,13 @@ module Actions
|
||||||
contact.email_history = contact.email
|
contact.email_history = contact.email
|
||||||
contact.save
|
contact.save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def validate_contact
|
||||||
|
return if @error || !contact.valid?
|
||||||
|
|
||||||
|
[:regex, :mx].each do |m|
|
||||||
|
contact.verify_email(check_level: m, single_email: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,6 +18,7 @@ module Actions
|
||||||
maybe_change_email if new_attributes[:email].present?
|
maybe_change_email if new_attributes[:email].present?
|
||||||
maybe_filtering_old_failed_records
|
maybe_filtering_old_failed_records
|
||||||
commit
|
commit
|
||||||
|
validate_contact
|
||||||
end
|
end
|
||||||
|
|
||||||
def maybe_change_email
|
def maybe_change_email
|
||||||
|
@ -25,12 +26,7 @@ module Actions
|
||||||
|
|
||||||
%i[regex mx].each do |m|
|
%i[regex mx].each do |m|
|
||||||
result = Actions::SimpleMailValidator.run(email: @new_attributes[:email], level: m)
|
result = Actions::SimpleMailValidator.run(email: @new_attributes[:email], level: m)
|
||||||
if result
|
next if result
|
||||||
@contact.validate_email_by_regex_and_mx
|
|
||||||
@contact.remove_force_delete_for_valid_contact
|
|
||||||
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
err_text = "email '#{new_attributes[:email]}' didn't pass validation"
|
err_text = "email '#{new_attributes[:email]}' didn't pass validation"
|
||||||
contact.add_epp_error('2005', nil, nil, "#{I18n.t(:parameter_value_syntax_error)} #{err_text}")
|
contact.add_epp_error('2005', nil, nil, "#{I18n.t(:parameter_value_syntax_error)} #{err_text}")
|
||||||
|
@ -128,5 +124,15 @@ module Actions
|
||||||
|
|
||||||
updated
|
updated
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def validate_contact
|
||||||
|
return if @error || !contact.valid?
|
||||||
|
|
||||||
|
[:regex, :mx].each do |m|
|
||||||
|
@contact.verify_email(check_level: m, single_email: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
@contact.remove_force_delete_for_valid_contact
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
module Actions
|
module Actions
|
||||||
class EmailCheck
|
class EmailCheck
|
||||||
attr_reader :email, :validation_eventable, :check_level
|
attr_reader :email, :validation_eventable, :check_level, :single_email
|
||||||
|
|
||||||
SAVE_RESULTS_BATCH_SIZE = 500
|
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
|
@email = email
|
||||||
@validation_eventable = validation_eventable
|
@validation_eventable = validation_eventable
|
||||||
@check_level = check_level || :mx
|
@check_level = check_level || :mx
|
||||||
|
@single_email = single_email
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
result = check_email(email)
|
result = check_email(email)
|
||||||
save_result(result)
|
single_email ? save_single_result(validation_eventable: validation_eventable, result: result) : save_result(result)
|
||||||
handle_logging(result)
|
handle_logging(result)
|
||||||
result.success
|
result.success
|
||||||
end
|
end
|
||||||
|
@ -48,6 +49,15 @@ module Actions
|
||||||
contact.validation_events.destroy_all if success
|
contact.validation_events.destroy_all if success
|
||||||
end
|
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)
|
def save_result(result)
|
||||||
contacts = Contact.where(email: email)
|
contacts = Contact.where(email: email)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
class VerifyEmailsJob < ApplicationJob
|
class VerifyEmailsJob < ApplicationJob
|
||||||
discard_on StandardError
|
discard_on StandardError
|
||||||
|
|
||||||
def perform(email:, check_level: 'mx')
|
def perform(email:, check_level: 'mx', single_check: false)
|
||||||
contact = Contact.find_by(email: email)
|
contact = Contact.find_by(email: email)
|
||||||
|
|
||||||
return logger.info "Contact #{email} not found!" if contact.nil?
|
return logger.info "Contact #{email} not found!" if contact.nil?
|
||||||
|
@ -11,7 +11,7 @@ class VerifyEmailsJob < ApplicationJob
|
||||||
validate_check_level(check_level)
|
validate_check_level(check_level)
|
||||||
|
|
||||||
logger.info "Trying to verify contact email #{email} with check_level #{check_level}"
|
logger.info "Trying to verify contact email #{email} with check_level #{check_level}"
|
||||||
contact.verify_email(check_level: check_level)
|
contact.verify_email(check_level: check_level, single_email: single_check)
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
handle_error(e)
|
handle_error(e)
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,17 +5,15 @@ module EmailVerifable
|
||||||
scope :recently_not_validated, -> { where.not(id: ValidationEvent.validated_ids_by(name)) }
|
scope :recently_not_validated, -> { where.not(id: ValidationEvent.validated_ids_by(name)) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_email_by_regex_and_mx
|
def validate_email_by_regex_and_mx(single_email: false)
|
||||||
# return if Rails.env.test?
|
verify_email(check_level: 'regex', single_email: single_email)
|
||||||
|
verify_email(check_level: 'mx', single_email: single_email)
|
||||||
verify_email(check_level: 'regex')
|
|
||||||
verify_email(check_level: 'mx')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_force_delete_for_valid_contact
|
def remove_force_delete_for_valid_contact
|
||||||
# return if Rails.env.test?
|
domain_with_fd = domains.select(&:force_delete_scheduled?)
|
||||||
|
|
||||||
domains.each do |domain|
|
domain_with_fd.each do |domain|
|
||||||
contact_emails_valid?(domain) ? domain.cancel_force_delete : nil
|
contact_emails_valid?(domain) ? domain.cancel_force_delete : nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -68,14 +66,15 @@ module EmailVerifable
|
||||||
process_error(:billing_email) unless result
|
process_error(:billing_email) unless result
|
||||||
end
|
end
|
||||||
|
|
||||||
def verify_email(check_level: 'regex')
|
def verify_email(check_level: 'regex', single_email: false)
|
||||||
verify(email: email, check_level: check_level)
|
verify(email: email, check_level: check_level, single_email: single_email)
|
||||||
end
|
end
|
||||||
|
|
||||||
def verify(email:, check_level: 'regex')
|
def verify(email:, check_level: 'regex', single_email: false)
|
||||||
action = Actions::EmailCheck.new(email: email,
|
action = Actions::EmailCheck.new(email: email,
|
||||||
validation_eventable: self,
|
validation_eventable: self,
|
||||||
check_level: check_level)
|
check_level: check_level,
|
||||||
|
single_email: single_email)
|
||||||
action.call
|
action.call
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
29
lib/tasks/verify_domain.rake
Normal file
29
lib/tasks/verify_domain.rake
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
require 'optparse'
|
||||||
|
require 'rake_option_parser_boilerplate'
|
||||||
|
require 'syslog/logger'
|
||||||
|
require 'active_record'
|
||||||
|
|
||||||
|
SPAM_PROTECT_TIMEOUT = 30.seconds
|
||||||
|
|
||||||
|
task verify_domain: :environment do
|
||||||
|
options = {
|
||||||
|
domain_name: nil,
|
||||||
|
check_level: 'mx',
|
||||||
|
spam_protect: false,
|
||||||
|
}
|
||||||
|
banner = 'Usage: rake verify_domain -- [options]'
|
||||||
|
options = RakeOptionParserBoilerplate.process_args(options: options,
|
||||||
|
banner: banner,
|
||||||
|
hash: opts_hash)
|
||||||
|
|
||||||
|
|
||||||
|
domain = Domain.find_by(name: options[:domain_name])
|
||||||
|
check_level = options[:check_level]
|
||||||
|
|
||||||
|
domain.domain_contacts.each do |dc|
|
||||||
|
dc.contact.verify_email(check_level: check_level, single_email: true)
|
||||||
|
|
||||||
|
Rails.logger.info "Validated contact with code #{dc.contact.code} and email #{dc.contact.email} of #{domain.name} domain"
|
||||||
|
Rails.logger.info "Result - #{dc.contact.validation_events.last.success}"
|
||||||
|
end
|
||||||
|
end
|
|
@ -375,6 +375,59 @@ class ContactTest < ActiveJob::TestCase
|
||||||
# assert_not @contact.domains.first.force_delete_scheduled?
|
# assert_not @contact.domains.first.force_delete_scheduled?
|
||||||
# end
|
# 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
|
private
|
||||||
|
|
||||||
def make_contact_free_of_domains_where_it_acts_as_a_registrant(contact)
|
def make_contact_free_of_domains_where_it_acts_as_a_registrant(contact)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue