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

@ -28,9 +28,8 @@ module Admin
# POST /admin/disputes
def create
@dispute = Dispute.new(dispute_params)
if @dispute.save
redirect_to @dispute, notice: 'Dispute was successfully created.'
redirect_to admin_disputes_url, notice: 'Dispute was successfully created.'
else
render :new
end
@ -39,16 +38,16 @@ module Admin
# PATCH/PUT /admin/disputes/1
def update
if @dispute.update(dispute_params)
redirect_to @dispute, notice: 'Dispute was successfully updated.'
redirect_to admin_disputes_url, notice: 'Dispute was successfully updated.'
else
render :edit
end
end
# DELETE /admin/disputes/1
def destroy
def delete
@dispute.destroy
redirect_to disputes_url, notice: 'Dispute was successfully destroyed.'
redirect_to admin_disputes_url, notice: 'Dispute was successfully destroyed.'
end
private
@ -60,7 +59,7 @@ module Admin
# Only allow a trusted parameter "white list" through.
def dispute_params
params.require(:dispute).permit(:domain_name, :password, :expires_at, :comment, :created_at)
params.require(:dispute).permit(:domain_name, :password, :starts_at, :comment)
end
end
end

View file

@ -104,6 +104,10 @@ module Epp
authorize! :update, @domain, @password
if @domain.update(params[:parsed_frame], current_user)
if @domain.disputed?
dispute = Dispute.active.find_by(domain_name: @domain.name)
dispute.close
end
if @domain.epp_pending_update.present?
render_epp_response '/epp/domains/success_pending'
else

View file

@ -31,6 +31,12 @@ class Registrant::DomainUpdateConfirmsController < RegistrantController
end
elsif params[:confirmed]
if @registrant_verification.domain_registrant_change_confirm!("email link, #{initiator}")
if @domain.disputed?
Rails.logger.info 'Closing domain dispute via RegistrantConfirmation'
dispute = Dispute.active.find_by(domain_name: @domain.name)
dispute.close
end
flash[:notice] = t(:registrant_domain_verification_confirmed)
redirect_to registrant_domain_update_confirm_path(@domain.id, confirmed: true)
else

View file

@ -4,10 +4,11 @@ class UpdateWhoisRecordJob < Que::Job
::PaperTrail.whodunnit = "job - #{self.class.name} - #{type}"
klass = case type
when 'reserved'then ReservedDomain
when 'blocked' then BlockedDomain
when 'domain' then Domain
end
when 'reserved' then ReservedDomain
when 'blocked' then BlockedDomain
when 'domain' then Domain
when 'disputed' then Dispute
end
Array(names).each do |name|
record = klass.find_by(name: name)
@ -19,8 +20,6 @@ class UpdateWhoisRecordJob < Que::Job
end
end
def update_domain(domain)
domain.whois_record ? domain.whois_record.save : domain.create_whois_record
end
@ -33,6 +32,9 @@ class UpdateWhoisRecordJob < Que::Job
update_reserved(record)
end
def update_disputed(record)
update_reserved(record)
end
# 1. deleting own
# 2. trying to regenerate reserved in order domain is still in the list
@ -41,6 +43,7 @@ class UpdateWhoisRecordJob < Que::Job
BlockedDomain.find_by(name: name).try(:generate_data)
ReservedDomain.find_by(name: name).try(:generate_data)
Dispute.active.find_by(domain_name: name).try(:generate_data)
end
def delete_reserved(name)
@ -51,4 +54,8 @@ class UpdateWhoisRecordJob < Que::Job
def delete_blocked(name)
delete_reserved(name)
end
def delete_disputed(name)
delete_reserved(name)
end
end

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