# frozen_string_literal: true require 'resolv' class NameserverRecordValidationJob < ApplicationJob include Dnsruby def perform(domain_name: nil) if domain_name.nil? domains = Domain.all.select { |domain| domain.created_at < Time.zone.now - NameserverValidator::VALIDATION_DOMAIN_PERIOD } .select { |domain| domain.nameservers.exists? } domains.each do |domain| domain.nameservers.each do |nameserver| next if nameserver.failed_validation? || nameserver.validated? result = NameserverValidator.run(domain_name: domain.name, nameserver: nameserver) if result[:result] add_nameserver_to_succesfully(nameserver) true else parse_result(result, nameserver) false end end end else domain = Domain.find_by(name: domain_name) return logger.info 'Domain not found' if domain.nil? if domain.created_at > Time.zone.now - NameserverValidator::VALIDATION_DOMAIN_PERIOD return logger.info "It should take #{NameserverValidator::VALIDATION_DOMAIN_PERIOD} hours after the domain was created" end return logger.info 'Domain not has nameservers' if domain.nameservers.empty? domain.nameservers.each do |nameserver| next if nameserver.failed_validation? result = NameserverValidator.run(domain_name: domain.name, nameserver: nameserver) if result[:result] add_nameserver_to_succesfully(nameserver) true else parse_result(result, nameserver) false end end end end private def add_nameserver_to_succesfully(nameserver) nameserver.validation_counter = nil nameserver.failed_validation_reason = nil nameserver.validation_datetime = Time.zone.now nameserver.save end def add_nameserver_to_failed(nameserver:, reason:, result_reason:) return cname_case_handle(nameserver: nameserver, reason: reason) if result_reason == 'cname' nameserver.validation_counter = 1 if nameserver.validation_counter.nil? nameserver.validation_counter = nameserver.validation_counter + 1 nameserver.failed_validation_reason = reason nameserver.save failed_log(text: reason, nameserver: nameserver, domain: nameserver.domain) if nameserver.failed_validation? end def cname_case_handle(nameserver:, reason:) nameserver.validation_datetime = Time.zone.now nameserver.failed_validation_reason = reason nameserver.save failed_log(text: reason, nameserver: nameserver, domain: nameserver.domain) end def parse_result(result, nameserver) domain = Domain.find(nameserver.domain_id) text = '' case result[:reason] when 'answer' text = "DNS Server **#{nameserver.hostname}** not responding" when 'serial' text = "Serial number for nameserver hostname **#{nameserver.hostname}** of #{nameserver.domain.name} doesn't present in zone. SOA validation failed." when 'cname' text = "Warning: SOA record expected but CNAME found instead. This setup can lead to unexpected errors when using the domain: hostname - **#{nameserver.hostname}** of #{nameserver.domain.name}" when 'not found' text = "Seems nameserver hostname **#{nameserver.hostname}** doesn't exist" when 'exception' text = "Something went wrong, exception reason: **#{result[:error_info]}**" when 'domain' text = "#{domain} zone is not in nameserver**#{nameserver.hostname}**" when 'glup record' text = "Hostname #{nameserver.hostname} didn't resovle by glue record to #{domain}" end logger.info text add_nameserver_to_failed(nameserver: nameserver, reason: text, result_reason: result[:reason]) false end def failed_log(text:, nameserver:, domain:) inform_to_tech_contact(domain: domain, nameserver: nameserver, text: text) inform_to_registrar(text: text, nameserver: nameserver) false end def inform_to_tech_contact(domain:, nameserver:, text: nil) # ContactNotification.notify_tech_contact(domain: domain, nameserver: nameserver, reason: 'nameserver') end def inform_to_registrar(nameserver:, text: nil) text = "Host record #{nameserver.hostname} of a domain #{nameserver.domain} is invalid. Please fix or contact the registrant. Problem with nameserver #{nameserver} - #{nameserver.failed_validation_reason}" logger.info text # ContactNotification.notify_registrar(domain: nameserver.domain, text: text) end def logger @logger ||= Rails.logger end end