internetee/registry

View on GitHub
app/jobs/nameserver_record_validation_job.rb

Summary

Maintainability
A
3 hrs
Test Coverage
C
70%
# 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