Add disputing logic for EPP

This commit is contained in:
Karl Erik Õunapuu 2020-04-24 16:04:58 +03:00
parent 7a7b2f9881
commit 0f2a290d64
17 changed files with 626 additions and 325 deletions

View file

@ -1,5 +1,89 @@
# frozen_string_literal: true
class Dispute < ApplicationRecord
validates :domain_name, :password, :starts_at, :expires_at, :comment,
presence: true
validates :domain_name, :password, :starts_at, :expires_at, presence: true
validates_uniqueness_of :domain_name, case_sensitive: true
before_validation :fill_empty_passwords
before_validation :set_expiry_date
validate :validate_domain_name
with_options on: :admin do
validate :validate_start_date
end
before_save :set_expiry_date
before_save :sync_reserved_password
after_destroy :remove_data
scope :expired, -> { where('expires_at < ?', Time.zone.today) }
scope :active, -> { where('expires_at > ? AND closed = 0', Time.zone.today) }
scope :closed, -> { where(closed: true) }
alias_attribute :name, :domain_name
def set_expiry_date
return if starts_at.blank?
self.expires_at = starts_at + Setting.dispute_period_in_months.months
end
def generate_password
self.password = SecureRandom.hex
end
def generate_data
return if Domain.where(name: domain_name).any?
wr = Whois::Record.find_or_initialize_by(name: domain_name)
wr.json = @json = generate_json # we need @json to bind to class
wr.save
end
def close
self.closed = true
save!
end
def generate_json
h = HashWithIndifferentAccess.new
h[:name] = domain_name
h[:status] = ['Disputed']
h
end
def remove_data
UpdateWhoisRecordJob.enqueue domain_name, 'disputed'
end
def fill_empty_passwords
generate_password if password.blank?
end
def sync_reserved_password
reserved_domain = ReservedDomain.find_by(name: domain_name)
generate_password if password.blank?
unless reserved_domain.nil?
reserved_domain.password = password
reserved_domain.save!
end
generate_data
end
private
def validate_start_date
return if starts_at.nil?
errors.add(:starts_at, :past) if starts_at.past?
end
def validate_domain_name
return unless domain_name
zone = domain_name.split('.').last
supported_zone = DNS::Zone.origins.include?(zone)
errors.add(:domain_name, :unsupported_zone) unless supported_zone
end
end

View file

@ -68,6 +68,10 @@ module DNS
ReservedDomain.where(name: name).any?
end
def disputed?
Dispute.active.where(domain_name: name).any?
end
def auctionable?
!not_auctionable?
end
@ -81,7 +85,7 @@ module DNS
attr_reader :name
def not_auctionable?
blocked? || reserved?
blocked? || reserved? || disputed?
end
def zone_with_same_origin?

View file

@ -90,6 +90,7 @@ class Domain < ApplicationRecord
validates :transfer_code, presence: true
validate :validate_reservation
def validate_reservation
return if persisted? || !in_reserved_list?
@ -99,6 +100,7 @@ class Domain < ApplicationRecord
end
return if ReservedDomain.pw_for(name) == reserved_pw
errors.add(:base, :invalid_auth_information_reserved)
end
@ -170,7 +172,7 @@ class Domain < ApplicationRecord
end
attr_accessor :registrant_typeahead, :update_me,
:epp_pending_update, :epp_pending_delete, :reserved_pw
:epp_pending_update, :epp_pending_delete, :reserved_pw, :disputed_pw
self.ignored_columns = %w[legacy_id legacy_registrar_id legacy_registrant_id]
@ -275,6 +277,10 @@ class Domain < ApplicationRecord
@in_reserved_list ||= ReservedDomain.by_domain(name).any?
end
def disputed?
Dispute.active.where(domain_name: name).any?
end
def pending_transfer
transfers.find_by(status: DomainTransfer::PENDING)
end

View file

@ -58,7 +58,8 @@ class Epp::Domain < Domain
'2003' => [ # Required parameter missing
[:registrant, :blank],
[:registrar, :blank],
[:base, :required_parameter_missing_reserved]
[:base, :required_parameter_missing_reserved],
[:base, :required_parameter_missing_disputed]
],
'2004' => [ # Parameter value range error
[:dnskeys, :out_of_range,
@ -88,7 +89,8 @@ class Epp::Domain < Domain
[:transfer_code, :wrong_pw]
],
'2202' => [
[:base, :invalid_auth_information_reserved]
[:base, :invalid_auth_information_reserved],
[:base, :invalid_auth_information_disputed]
],
'2302' => [ # Object exists
[:name_dirty, :taken, { value: { obj: 'name', val: name_dirty } }],
@ -154,6 +156,7 @@ class Epp::Domain < Domain
at[:period_unit] = Epp::Domain.parse_period_unit_from_frame(frame) || 'y'
at[:reserved_pw] = frame.css('reserved > pw').text
at[:disputed_pw] = frame.css('disputed > pw').text
# at[:statuses] = domain_statuses_attrs(frame, action)
at[:nameservers_attributes] = nameservers_attrs(frame, action)
@ -475,6 +478,16 @@ class Epp::Domain < Domain
same_registrant_as_current = (registrant.code == frame.css('registrant').text)
if !same_registrant_as_current && disputed?
disputed_pw = frame.css('disputed > pw').text
if disputed_pw.blank?
add_epp_error('2304', nil, nil, 'Required parameter missing; disputed pw element required for dispute domains')
else
dispute = Dispute.active.find_by(domain_name: name, password: disputed_pw)
add_epp_error('2202', nil, nil, 'Invalid authorization information; invalid disputed>pw value') if dispute.nil?
end
end
if !same_registrant_as_current && errors.empty? && verify &&
Setting.request_confrimation_on_registrant_change_enabled &&
frame.css('registrant').present? &&
@ -706,6 +719,11 @@ class Epp::Domain < Domain
def can_be_deleted?
if disputed?
errors.add(:base, :domain_status_prohibits_operation)
return false
end
begin
errors.add(:base, :domain_status_prohibits_operation)
return false

View file

@ -46,6 +46,7 @@ class Setting < RailsSettings::Base
expire_warning_period
redemption_grace_period
expire_pending_confirmation
dispute_period_in_months
]
end