Merge remote-tracking branch 'origin/add-registrant-api-token-log' into add-role-filter-to-registrant-api

This commit is contained in:
Karl Erik Õunapuu 2021-02-23 13:48:05 +02:00
commit f60bf4013c
No known key found for this signature in database
GPG key ID: C9DD647298A34764
60 changed files with 1153 additions and 178 deletions

View file

@ -19,6 +19,11 @@ module Actions
return
end
if contact.delete_prohibited?
contact.errors.add(:statuses, :delete_prohibited)
return
end
commit
end

View file

@ -1,2 +1,26 @@
class AdminDomainContact < DomainContact
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/MethodLength
def self.replace(current_contact, new_contact)
affected_domains = []
skipped_domains = []
admin_contacts = where(contact: current_contact)
admin_contacts.each do |admin_contact|
if admin_contact.domain.bulk_update_prohibited?
skipped_domains << admin_contact.domain.name
next
end
begin
admin_contact.contact = new_contact
admin_contact.save!
affected_domains << admin_contact.domain.name
rescue ActiveRecord::RecordNotUnique
skipped_domains << admin_contact.domain.name
end
end
[affected_domains.sort, skipped_domains.sort]
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/MethodLength
end

View file

@ -1,5 +1,6 @@
class BouncedMailAddress < ApplicationRecord
validates :email, :message_id, :bounce_type, :bounce_subtype, :action, :status, presence: true
after_destroy :destroy_aws_suppression
def bounce_reason
"#{action} (#{status} #{diagnostic})"
@ -25,4 +26,20 @@ class BouncedMailAddress < ApplicationRecord
diagnostic: bounced_record['diagnosticCode'],
}
end
def destroy_aws_suppression
return unless BouncedMailAddress.ses_configured?
res = Aws::SESV2::Client.new.delete_suppressed_destination(email_address: email)
res.successful?
rescue Aws::SESV2::Errors::ServiceError => e
logger.warn("Suppression not removed. #{e}")
end
def self.ses_configured?
ses ||= Aws::SESV2::Client.new
ses.config.credentials.access_key_id.present?
rescue Aws::Errors::MissingRegionError
false
end
end

View file

@ -11,6 +11,13 @@ module Concerns::Contact::Identical
ident_country_code
org_name
]
IDENTICAL_ATTRIBUTES = %w[
ident
ident_type
ident_country_code
].freeze
private_constant :IDENTIFIABLE_ATTRIBUTES
def identical(registrar)
@ -20,6 +27,12 @@ module Concerns::Contact::Identical
.where.not(id: id).take
end
def identical_to?(contact)
IDENTICAL_ATTRIBUTES.all? do |attribute|
attributes[attribute] == contact.attributes[attribute]
end
end
private
def identifiable_hash

View file

@ -1,6 +1,12 @@
module Concerns::Domain::Deletable
extend ActiveSupport::Concern
DELETE_STATUSES = [
DomainStatus::PENDING_DELETE_CONFIRMATION,
DomainStatus::PENDING_DELETE,
DomainStatus::FORCE_DELETE,
].freeze
private
def delete_later

View file

@ -11,6 +11,11 @@ module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength
lambda {
where("(force_delete_data->>'contact_notification_sent_date') is null")
}
HOLD_STATUSES = [
DomainStatus::SERVER_HOLD,
DomainStatus::CLIENT_HOLD,
].freeze
end
class_methods do
@ -19,6 +24,10 @@ module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength
end
end
def hold_status?
HOLD_STATUSES.any? { |status| statuses.include? status }
end
def notification_template(explicit: nil)
reason = explicit&.downcase
return reason if %w[invalid_email invalid_phone].include?(reason)

View file

@ -12,6 +12,7 @@ module Concerns
statuses << DomainStatus::SERVER_DELETE_PROHIBITED
statuses << DomainStatus::SERVER_TRANSFER_PROHIBITED
self.locked_by_registrant_at = Time.zone.now
alert_registrar_lock_changes!(lock: true)
save!
end
@ -42,10 +43,21 @@ module Concerns
statuses.delete(DomainStatus::SERVER_DELETE_PROHIBITED)
statuses.delete(DomainStatus::SERVER_TRANSFER_PROHIBITED)
self.locked_by_registrant_at = nil
alert_registrar_lock_changes!(lock: false)
save!
end
end
def alert_registrar_lock_changes!(lock: true)
translation = lock ? 'locked' : 'unlocked'
registrar.notifications.create!(
text: I18n.t("notifications.texts.registrar_#{translation}",
domain_name: name),
attached_obj_id: name,
attached_obj_type: self.class.name
)
end
end
end
end

View file

@ -0,0 +1,40 @@
class ContactRequest < ApplicationRecord
establish_connection :"whois_#{Rails.env}"
self.table_name = 'contact_requests'
STATUS_NEW = 'new'.freeze
STATUS_CONFIRMED = 'confirmed'.freeze
STATUS_SENT = 'sent'.freeze
STATUSES = [STATUS_NEW, STATUS_CONFIRMED, STATUS_SENT].freeze
validates :whois_record_id, presence: true
validates :email, presence: true
validates :name, presence: true
validates :status, inclusion: { in: STATUSES }
attr_readonly :secret,
:valid_to
def self.save_record(params)
contact_request = new(params)
contact_request.secret = create_random_secret
contact_request.valid_to = set_valid_to_24_hours_from_now
contact_request.status = STATUS_NEW
contact_request.save!
contact_request
end
def update_status(params)
self.status = params['status']
self.ip_address = params['ip']
save!
end
def self.create_random_secret
SecureRandom.hex(64)
end
def self.set_valid_to_24_hours_from_now
(Time.zone.now + 24.hours)
end
end

View file

@ -107,13 +107,13 @@ class Domain < ApplicationRecord
validate :status_is_consistant
def status_is_consistant
has_error = (statuses.include?(DomainStatus::SERVER_HOLD) && statuses.include?(DomainStatus::SERVER_MANUAL_INZONE))
unless has_error
if (statuses & [DomainStatus::PENDING_DELETE_CONFIRMATION, DomainStatus::PENDING_DELETE, DomainStatus::FORCE_DELETE]).any?
has_error = statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED
end
has_error = (hold_status? && statuses.include?(DomainStatus::SERVER_MANUAL_INZONE))
unless has_error
if (statuses & DELETE_STATUSES).any?
has_error = statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED
end
errors.add(:domains, I18n.t(:object_status_prohibits_operation)) if has_error
end
errors.add(:domains, I18n.t(:object_status_prohibits_operation)) if has_error
end
attr_accessor :is_admin

View file

@ -42,17 +42,12 @@ class Epp::Contact < Contact
)
end
def check_availability(codes)
def check_availability(codes, reg:)
codes = [codes] if codes.is_a?(String)
res = []
codes.each do |x|
contact = find_by_epp_code(x)
if contact
res << { code: contact.code, avail: 0, reason: 'in use' }
else
res << { code: x, avail: 1 }
end
codes.map { |c| c.include?(':') ? c : "#{reg}:#{c}" }.map { |c| c.strip.upcase }.each do |x|
c = find_by_epp_code(x)
res << (c ? { code: c.code, avail: 0, reason: 'in use' } : { code: x, avail: 1 })
end
res
@ -87,8 +82,11 @@ class Epp::Contact < Contact
'2302' => [ # Object exists
[:code, :epp_id_taken]
],
'2304' => [ # Status prohibits operation
[:statuses, :delete_prohibited],
],
'2305' => [ # Association exists
[:domains, :exist]
[:domains, :exist],
]
}
end

View file

@ -495,7 +495,7 @@ class Epp::Domain < Domain
registrant_verification_needed = false
# registrant block may not be present, so we need this to rule out false positives
if frame.css('registrant').text.present?
registrant_verification_needed = (registrant.code != frame.css('registrant').text)
registrant_verification_needed = verification_needed?(code: frame.css('registrant').text)
end
if registrant_verification_needed && disputed?
@ -612,7 +612,6 @@ class Epp::Domain < Domain
statuses.delete(DomainStatus::SERVER_HOLD)
statuses.delete(DomainStatus::EXPIRED)
statuses.delete(DomainStatus::SERVER_UPDATE_PROHIBITED)
cancel_pending_delete
save
@ -798,4 +797,13 @@ class Epp::Domain < Domain
result
end
end
private
def verification_needed?(code:)
new_registrant = Registrant.find_by(code: code)
return false if new_registrant.try(:identical_to?, registrant)
registrant.code != code
end
end

View file

@ -25,6 +25,10 @@ class Notification < ApplicationRecord
''
end
def registry_lock?
text.include?('has been locked') || text.include?('has been unlocked')
end
private
def set_defaults

View file

@ -4,8 +4,13 @@ class WhiteIp < ApplicationRecord
validate :valid_ipv4?
validate :valid_ipv6?
validate :validate_ipv4_and_ipv6
before_save :normalize_blank_values
def normalize_blank_values
%i[ipv4 ipv6].each { |c| self[c].present? || self[c] = nil }
end
def validate_ipv4_and_ipv6
return if ipv4.present? || ipv6.present?
errors.add(:base, I18n.t(:ipv4_or_ipv6_must_be_present))
@ -50,10 +55,10 @@ class WhiteIp < ApplicationRecord
def ids_including(ip)
ipv4 = ipv6 = []
if check_ip4(ip).present?
ipv4 = select { |white_ip| IPAddr.new(white_ip.ipv4, Socket::AF_INET) === check_ip4(ip) }
ipv4 = select { |white_ip| check_ip4(white_ip.ipv4) === check_ip4(ip) }
end
if check_ip6(ip).present?
ipv6 = select { |white_ip| IPAddr.new(white_ip.ipv6, Socket::AF_INET6) === check_ip6(ip) }
ipv6 = select { |white_ip| check_ip6(white_ip.ipv6) === check_ip6(ip) }
end
(ipv4 + ipv6).pluck(:id).flatten.uniq
end

View file

@ -97,7 +97,9 @@ class WhoisRecord < ApplicationRecord
end
def destroy_whois_record
Whois::Record.without_auctions.where(name: name).delete_all
return if Auction.find_by(domain: name).present?
Whois::Record.where(name: name).delete_all
end
private