Merge remote-tracking branch 'origin/master' into repp-domains

This commit is contained in:
Karl Erik Õunapuu 2020-12-29 12:47:50 +02:00
commit 221e4ba578
No known key found for this signature in database
GPG key ID: C9DD647298A34764
140 changed files with 2575 additions and 731 deletions

View file

@ -109,6 +109,7 @@ class Ability
can :destroy, :pending
can :create, :zonefile
can :access, :settings_menu
can :manage, BouncedMailAddress
end
def static_registrant

View file

@ -169,16 +169,19 @@ module Actions
invalid = false
params[:statuses].each do |s|
unless DomainStatus::CLIENT_STATUSES.include?(s[:status])
domain.add_epp_error('2303', 'status', s[:status], %i[domain_statuses not_found])
domain.add_epp_error('2303', 'status', s[:status], %i[statuses not_found])
invalid = true
end
end
return if invalid
params[:statuses].select { |s| s[:action] == 'rem' }.each do |s|
if domain.statuses.include?(s[:status])
rem << s[:status]
else
domain.add_epp_error('2303', 'status', s[:status], %i[domain_statuses not_found])
STDOUT << 'AAAAAH'
domain.add_epp_error('2303', 'status', s[:status], %i[statuses not_found])
invalid = true
end
end

View file

@ -0,0 +1,28 @@
class BouncedMailAddress < ApplicationRecord
validates :email, :message_id, :bounce_type, :bounce_subtype, :action, :status, presence: true
def bounce_reason
"#{action} (#{status} #{diagnostic})"
end
def self.record(json)
bounced_records = json['bounce']['bouncedRecipients']
bounced_records.each do |record|
bounce_record = BouncedMailAddress.new(params_from_json(json, record))
bounce_record.save
end
end
def self.params_from_json(json, bounced_record)
{
email: bounced_record['emailAddress'],
message_id: json['mail']['messageId'],
bounce_type: json['bounce']['bounceType'],
bounce_subtype: json['bounce']['bounceSubType'],
action: bounced_record['action'],
status: bounced_record['status'],
diagnostic: bounced_record['diagnosticCode'],
}
end
end

View file

@ -20,6 +20,6 @@ module Concerns::Domain::Deletable
end
def deletion_deadline
delete_date + 24.hours
(delete_date || Time.zone.now) + 24.hours
end
end
end

View file

@ -33,33 +33,14 @@ module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength
statuses.include?(DomainStatus::FORCE_DELETE)
end
def should_notify_on_soft_force_delete?
force_delete_scheduled? && contact_notification_sent_date.blank? &&
force_delete_start.to_date <= Time.zone.now.to_date && force_delete_type.to_sym == :soft &&
!statuses.include?(DomainStatus::CLIENT_HOLD)
end
def client_holdable?
force_delete_scheduled? && !statuses.include?(DomainStatus::CLIENT_HOLD) &&
force_delete_start.present? && force_delete_lte_today && force_delete_lte_valid_date
end
def force_delete_lte_today
force_delete_start + Setting.expire_warning_period.days <= Time.zone.now
end
def force_delete_lte_valid_date
force_delete_start + Setting.expire_warning_period.days <= valid_to
end
def schedule_force_delete(type: :fast_track, notify_by_email: false)
ForceDeleteInteraction::SetForceDelete.run(domain: self,
type: type,
notify_by_email: notify_by_email)
Domains::ForceDelete::SetForceDelete.run(domain: self,
type: type,
notify_by_email: notify_by_email)
end
def cancel_force_delete
CancelForceDeleteInteraction::CancelForceDelete.run(domain: self)
Domains::CancelForceDelete::CancelForceDelete.run(domain: self)
end
def outzone_date

View file

@ -1,34 +0,0 @@
module Concerns
module Job
module ForceDelete
extend ActiveSupport::Concern
class_methods do
def start_client_hold
log_prepare_client_hold
::PaperTrail.request.whodunnit = "cron - #{__method__}"
::Domain.force_delete_scheduled.each do |domain|
proceed_client_hold(domain: domain)
end
log_end_end_force_delete_job
end
def proceed_client_hold(domain:)
notify_on_grace_period(domain) if domain.should_notify_on_soft_force_delete?
return unless domain.client_holdable?
domain.statuses << DomainStatus::CLIENT_HOLD
log_start_client_hold(domain)
domain.save(validate: false)
notify_client_hold(domain)
log_end_end_client_hold(domain)
end
end
end
end
end

View file

@ -1,34 +0,0 @@
module Concerns
module Job
module ForceDeleteLogging
extend ActiveSupport::Concern
class_methods do
def log_prepare_client_hold
return if Rails.env.test?
STDOUT << "#{Time.zone.now.utc} - Setting client_hold to domains\n"
end
def log_start_client_hold(domain)
return if Rails.env.test?
STDOUT << "#{Time.zone.now.utc} DomainCron.start_client_hold: ##{domain.id} "\
"(#{domain.name}) #{domain.changes}\n"
end
def log_end_end_client_hold(domain)
return if Rails.env.test?
STDOUT << "#{Time.zone.now.utc} - Successfully set client_hold on (#{domain.name})"
end
def log_end_end_force_delete_job
return if Rails.env.test?
STDOUT << "#{Time.zone.now.utc} - All client_hold setting are done\n"
end
end
end
end
end

View file

@ -1,31 +0,0 @@
module Concerns
module Job
module ForceDeleteNotify
extend ActiveSupport::Concern
class_methods do
def notify_client_hold(domain)
domain.registrar.notifications.create!(text: I18n.t('force_delete_set_on_domain',
domain_name: domain.name,
outzone_date: domain.outzone_date,
purge_date: domain.purge_date))
end
def notify_on_grace_period(domain)
domain.registrar.notifications.create!(text: I18n.t('grace_period_started_domain',
domain_name: domain.name,
date: domain.force_delete_start))
send_mail(domain) if domain.template_name.present?
domain.update(contact_notification_sent_date: Time.zone.today)
end
def send_mail(domain)
DomainDeleteMailer.forced(domain: domain,
registrar: domain.registrar,
registrant: domain.registrant,
template_name: domain.template_name).deliver_now
end
end
end
end
end

View file

@ -347,19 +347,24 @@ class Contact < ApplicationRecord
@desc = {}
registrant_domains.each do |dom|
@desc[dom.name] ||= []
@desc[dom.name] << :registrant
@desc[dom.name] ||= { id: dom.uuid, roles: [] }
@desc[dom.name][:roles] << :registrant
end
domain_contacts.each do |dc|
@desc[dc.domain.name] ||= []
@desc[dc.domain.name] << dc.name.downcase.to_sym
@desc[dc.domain.name] ||= { id: dc.domain.uuid, roles: [] }
@desc[dc.domain.name][:roles] << dc.name.downcase.to_sym
@desc[dc.domain.name] = @desc[dc.domain.name].compact
end
@desc
end
def related_domains
a = related_domain_descriptions
a.keys.map { |d| { name: d, id: a[d][:id], roles: a[d][:roles] } }
end
def status_notes_array=(notes)
self.status_notes = {}
notes ||= []

View file

@ -327,6 +327,7 @@ class Domain < ApplicationRecord
end
def notify_registrar(message_key)
# TODO: To be deleted with DomainDeleteConfirm refactoring
registrar.notifications.create!(
text: "#{I18n.t(message_key)}: #{name}",
attached_obj_id: id,
@ -335,11 +336,13 @@ class Domain < ApplicationRecord
end
def preclean_pendings
# TODO: To be deleted with refactoring
self.registrant_verification_token = nil
self.registrant_verification_asked_at = nil
end
def clean_pendings!
# TODO: To be deleted with refactoring
preclean_pendings
self.pending_json = {}
statuses.delete(DomainStatus::PENDING_DELETE_CONFIRMATION)
@ -418,7 +421,7 @@ class Domain < ApplicationRecord
pending_delete_confirmation!
save(validate: false) # should check if this did succeed
DomainDeleteConfirmEmailJob.enqueue(id)
Domains::DeleteConfirmEmail::SendRequest.run(domain: self)
end
def cancel_pending_delete
@ -482,12 +485,6 @@ class Domain < ApplicationRecord
Registrant.find_by(id: pending_json['new_registrant_id'])
end
def set_graceful_expired
self.outzone_at = expire_time + self.class.expire_warning_period
self.delete_date = outzone_at + self.class.redemption_grace_period
self.statuses |= [DomainStatus::EXPIRED]
end
def pending_update?
statuses.include?(DomainStatus::PENDING_UPDATE)
end

View file

@ -1,84 +1,17 @@
class DomainCron
include Concerns::Job::ForceDelete
include Concerns::Job::ForceDeleteLogging
include Concerns::Job::ForceDeleteNotify
def self.clean_expired_pendings
STDOUT << "#{Time.zone.now.utc} - Clean expired domain pendings\n" unless Rails.env.test?
::PaperTrail.request.whodunnit = "cron - #{__method__}"
expire_at = Setting.expire_pending_confirmation.hours.ago
count = 0
expired_pending_domains = Domain.where('registrant_verification_asked_at <= ?', expire_at)
expired_pending_domains.each do |domain|
unless domain.pending_update? || domain.pending_delete? || domain.pending_delete_confirmation?
msg = "#{Time.zone.now.utc} - ISSUE: DOMAIN #{domain.id}: #{domain.name} IS IN EXPIRED PENDING LIST, " \
"but no pendingDelete/pendingUpdate state present!\n"
STDOUT << msg unless Rails.env.test?
next
end
count += 1
if domain.pending_update?
RegistrantChangeExpiredEmailJob.enqueue(domain.id)
end
if domain.pending_delete? || domain.pending_delete_confirmation?
DomainDeleteMailer.expired(domain).deliver_now
end
domain.preclean_pendings
domain.clean_pendings!
unless Rails.env.test?
STDOUT << "#{Time.zone.now.utc} DomainCron.clean_expired_pendings: ##{domain.id} (#{domain.name})\n"
end
UpdateWhoisRecordJob.enqueue domain.name, 'domain'
end
STDOUT << "#{Time.zone.now.utc} - Successfully cancelled #{count} domain pendings\n" unless Rails.env.test?
count
Domains::ExpiredPendings::CleanAll.run!
end
def self.start_expire_period
::PaperTrail.request.whodunnit = "cron - #{__method__}"
domains = Domain.expired
marked = 0
real = 0
domains.each do |domain|
next unless domain.expirable?
real += 1
domain.set_graceful_expired
STDOUT << "#{Time.zone.now.utc} DomainCron.start_expire_period: ##{domain.id} (#{domain.name}) #{domain.changes}\n" unless Rails.env.test?
send_time = domain.valid_to + Setting.expiration_reminder_mail.to_i.days
saved = domain.save(validate: false)
if saved
DomainExpireEmailJob.enqueue(domain.id, run_at: send_time)
marked += 1
end
end
STDOUT << "#{Time.zone.now.utc} - Successfully expired #{marked} of #{real} domains\n" unless Rails.env.test?
Domains::ExpirePeriod::Start.run!
end
def self.start_redemption_grace_period
STDOUT << "#{Time.zone.now.utc} - Setting server_hold to domains\n" unless Rails.env.test?
Domains::RedemptionGracePeriod::Start.run!
end
::PaperTrail.request.whodunnit = "cron - #{__method__}"
domains = Domain.outzone_candidates
marked = 0
real = 0
domains.each do |domain|
next unless domain.server_holdable?
real += 1
domain.statuses << DomainStatus::SERVER_HOLD
STDOUT << "#{Time.zone.now.utc} DomainCron.start_redemption_grace_period: ##{domain.id} (#{domain.name}) #{domain.changes}\n" unless Rails.env.test?
domain.save(validate: false) and marked += 1
end
STDOUT << "#{Time.zone.now.utc} - Successfully set server_hold to #{marked} of #{real} domains\n" unless Rails.env.test?
marked
def self.start_client_hold
Domains::ClientHold::SetClientHold.run!
end
end

View file

@ -18,24 +18,24 @@ class RegistrantVerification < ApplicationRecord
def domain_registrant_change_confirm!(initiator)
self.action_type = DOMAIN_REGISTRANT_CHANGE
self.action = CONFIRMED
DomainUpdateConfirmJob.enqueue domain.id, CONFIRMED, initiator if save
DomainUpdateConfirmJob.perform_later domain.id, CONFIRMED, initiator if save
end
def domain_registrant_change_reject!(initiator)
self.action_type = DOMAIN_REGISTRANT_CHANGE
self.action = REJECTED
DomainUpdateConfirmJob.run domain.id, REJECTED, initiator if save
DomainUpdateConfirmJob.perform_later domain.id, REJECTED, initiator if save
end
def domain_registrant_delete_confirm!(initiator)
self.action_type = DOMAIN_DELETE
self.action = CONFIRMED
DomainDeleteConfirmJob.enqueue domain.id, CONFIRMED, initiator if save
DomainDeleteConfirmJob.perform_later domain.id, CONFIRMED, initiator if save
end
def domain_registrant_delete_reject!(initiator)
self.action_type = DOMAIN_DELETE
self.action = REJECTED
DomainDeleteConfirmJob.enqueue domain.id, REJECTED, initiator if save
DomainDeleteConfirmJob.perform_later domain.id, REJECTED, initiator if save
end
end

33
app/models/repp_api.rb Normal file
View file

@ -0,0 +1,33 @@
class ReppApi
def self.bulk_renew(domains, period, registrar)
payload = { domains: domains, renew_period: period }
uri = URI.parse("#{ENV['repp_url']}domains/renew/bulk")
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
req.body = payload.to_json
ReppApi.request(req, uri, registrar: registrar).body
end
def self.request(request, uri, registrar:)
request.basic_auth(registrar.username, registrar.plain_text_password) if registrar
client_cert = Rails.env.test? ? nil : File.read(ENV['cert_path'])
client_key = Rails.env.test? ? nil : File.read(ENV['key_path'])
params = ReppApi.compose_ca_auth_params(uri, client_cert, client_key)
Net::HTTP.start(uri.hostname, uri.port, params) do |http|
http.request(request)
end
end
def self.compose_ca_auth_params(uri, client_cert, client_key)
params = { use_ssl: (uri.scheme == 'https') }
params[:verify_mode] = OpenSSL::SSL::VERIFY_NONE if Rails.env.test? || Rails.env.development?
unless Rails.env.test?
params[:cert] = OpenSSL::X509::Certificate.new(client_cert)
params[:key] = OpenSSL::PKey::RSA.new(client_key)
end
params
end
end

View file

@ -5,19 +5,20 @@ class TechDomainContact < DomainContact
skipped_domains = []
tech_contacts = where(contact: current_contact)
transaction do
tech_contacts.each do |tech_contact|
if tech_contact.domain.discarded?
skipped_domains << tech_contact.domain.name
next
end
tech_contacts.each do |tech_contact|
if tech_contact.domain.discarded?
skipped_domains << tech_contact.domain.name
next
end
begin
tech_contact.contact = new_contact
tech_contact.save!
affected_domains << tech_contact.domain.name
rescue ActiveRecord::RecordNotUnique
skipped_domains << tech_contact.domain.name
end
end
return affected_domains.sort, skipped_domains.sort
[affected_domains.sort, skipped_domains.sort]
end
end