mirror of
https://github.com/internetee/registry.git
synced 2025-07-21 18:26:06 +02:00
Merge remote-tracking branch 'origin/master' into 1739-ns-bulk-change-test-and-whois-update
This commit is contained in:
commit
c1aa286e90
192 changed files with 5154 additions and 1343 deletions
|
@ -109,6 +109,7 @@ class Ability
|
|||
can :destroy, :pending
|
||||
can :create, :zonefile
|
||||
can :access, :settings_menu
|
||||
can :manage, BouncedMailAddress
|
||||
end
|
||||
|
||||
def static_registrant
|
||||
|
|
81
app/models/actions/contact_create.rb
Normal file
81
app/models/actions/contact_create.rb
Normal file
|
@ -0,0 +1,81 @@
|
|||
module Actions
|
||||
class ContactCreate
|
||||
attr_reader :contact, :legal_document, :ident
|
||||
|
||||
def initialize(contact, legal_document, ident)
|
||||
@contact = contact
|
||||
@legal_document = legal_document
|
||||
@ident = ident
|
||||
end
|
||||
|
||||
def call
|
||||
maybe_remove_address
|
||||
maybe_attach_legal_doc
|
||||
validate_ident
|
||||
commit
|
||||
end
|
||||
|
||||
def maybe_remove_address
|
||||
return if Contact.address_processing?
|
||||
|
||||
contact.city = nil
|
||||
contact.zip = nil
|
||||
contact.street = nil
|
||||
contact.state = nil
|
||||
contact.country_code = nil
|
||||
end
|
||||
|
||||
def validate_ident
|
||||
validate_ident_integrity
|
||||
validate_ident_birthday
|
||||
|
||||
identifier = ::Contact::Ident.new(code: ident[:ident], type: ident[:ident_type],
|
||||
country_code: ident[:ident_country_code])
|
||||
|
||||
identifier.validate
|
||||
contact.identifier = identifier
|
||||
end
|
||||
|
||||
def validate_ident_integrity
|
||||
return if ident.blank?
|
||||
|
||||
if ident[:ident_type].blank?
|
||||
contact.add_epp_error('2003', nil, 'ident_type',
|
||||
I18n.t('errors.messages.required_ident_attribute_missing'))
|
||||
@error = true
|
||||
elsif !%w[priv org birthday].include?(ident[:ident_type])
|
||||
contact.add_epp_error('2003', nil, 'ident_type', 'Invalid ident type')
|
||||
@error = true
|
||||
end
|
||||
end
|
||||
|
||||
def validate_ident_birthday
|
||||
return if ident.blank?
|
||||
return unless ident[:ident_type] != 'birthday' && ident[:ident_country_code].blank?
|
||||
|
||||
contact.add_epp_error('2003', nil, 'ident_country_code',
|
||||
I18n.t('errors.messages.required_ident_attribute_missing'))
|
||||
@error = true
|
||||
end
|
||||
|
||||
def maybe_attach_legal_doc
|
||||
return unless legal_document
|
||||
|
||||
doc = LegalDocument.create(
|
||||
documentable_type: Contact,
|
||||
document_type: legal_document[:type], body: legal_document[:body]
|
||||
)
|
||||
|
||||
contact.legal_documents = [doc]
|
||||
contact.legal_document_id = doc.id
|
||||
end
|
||||
|
||||
def commit
|
||||
contact.id = nil # new record
|
||||
return false if @error
|
||||
|
||||
contact.generate_code
|
||||
contact.save
|
||||
end
|
||||
end
|
||||
end
|
41
app/models/actions/contact_delete.rb
Normal file
41
app/models/actions/contact_delete.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
module Actions
|
||||
class ContactDelete
|
||||
attr_reader :contact
|
||||
attr_reader :new_attributes
|
||||
attr_reader :legal_document
|
||||
attr_reader :ident
|
||||
attr_reader :user
|
||||
|
||||
def initialize(contact, legal_document = nil)
|
||||
@legal_document = legal_document
|
||||
@contact = contact
|
||||
end
|
||||
|
||||
def call
|
||||
maybe_attach_legal_doc
|
||||
|
||||
if contact.linked?
|
||||
contact.errors.add(:domains, :exist)
|
||||
return
|
||||
end
|
||||
|
||||
commit
|
||||
end
|
||||
|
||||
def maybe_attach_legal_doc
|
||||
return unless legal_document
|
||||
|
||||
document = contact.legal_documents.create(
|
||||
document_type: legal_document[:type],
|
||||
body: legal_document[:body]
|
||||
)
|
||||
|
||||
contact.legal_document_id = document.id
|
||||
contact.save
|
||||
end
|
||||
|
||||
def commit
|
||||
contact.destroy
|
||||
end
|
||||
end
|
||||
end
|
|
@ -17,7 +17,7 @@ module Actions
|
|||
def call
|
||||
maybe_remove_address
|
||||
maybe_update_statuses
|
||||
maybe_update_ident
|
||||
maybe_update_ident if ident.present?
|
||||
maybe_attach_legal_doc
|
||||
commit
|
||||
end
|
||||
|
@ -53,7 +53,11 @@ module Actions
|
|||
end
|
||||
|
||||
def maybe_update_ident
|
||||
return unless ident[:ident]
|
||||
unless ident.is_a?(Hash)
|
||||
contact.add_epp_error('2308', nil, nil, I18n.t('epp.contacts.errors.valid_ident'))
|
||||
@error = true
|
||||
return
|
||||
end
|
||||
|
||||
if contact.identifier.valid?
|
||||
submitted_ident = ::Contact::Ident.new(code: ident[:ident],
|
||||
|
|
74
app/models/actions/domain_transfer.rb
Normal file
74
app/models/actions/domain_transfer.rb
Normal file
|
@ -0,0 +1,74 @@
|
|||
module Actions
|
||||
class DomainTransfer
|
||||
attr_reader :domain
|
||||
attr_reader :transfer_code
|
||||
attr_reader :legal_document
|
||||
attr_reader :ident
|
||||
attr_reader :user
|
||||
|
||||
def initialize(domain, transfer_code, user)
|
||||
@domain = domain
|
||||
@transfer_code = transfer_code
|
||||
@user = user
|
||||
end
|
||||
|
||||
def call
|
||||
return unless domain_exists?
|
||||
return unless valid_transfer_code?
|
||||
|
||||
run_validations
|
||||
|
||||
# return domain.pending_transfer if domain.pending_transfer
|
||||
# attach_legal_document(::Deserializers::Xml::LegalDocument.new(frame).call)
|
||||
|
||||
return if domain.errors[:epp_errors].any?
|
||||
|
||||
commit
|
||||
end
|
||||
|
||||
def domain_exists?
|
||||
return true if domain.persisted?
|
||||
|
||||
domain.add_epp_error('2303', nil, nil, 'Object does not exist')
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def run_validations
|
||||
validate_registrar
|
||||
validate_eligilibty
|
||||
validate_not_discarded
|
||||
end
|
||||
|
||||
def valid_transfer_code?
|
||||
return true if transfer_code == domain.transfer_code
|
||||
|
||||
domain.add_epp_error('2202', nil, nil, 'Invalid authorization information')
|
||||
false
|
||||
end
|
||||
|
||||
def validate_registrar
|
||||
return unless user == domain.registrar
|
||||
|
||||
domain.add_epp_error('2002', nil, nil,
|
||||
I18n.t(:domain_already_belongs_to_the_querying_registrar))
|
||||
end
|
||||
|
||||
def validate_eligilibty
|
||||
return unless domain.non_transferable?
|
||||
|
||||
domain.add_epp_error('2304', nil, nil, 'Object status prohibits operation')
|
||||
end
|
||||
|
||||
def validate_not_discarded
|
||||
return unless domain.discarded?
|
||||
|
||||
domain.add_epp_error('2106', nil, nil, 'Object is not eligible for transfer')
|
||||
end
|
||||
|
||||
def commit
|
||||
bare_domain = Domain.find(domain.id)
|
||||
::DomainTransfer.request(bare_domain, user)
|
||||
end
|
||||
end
|
||||
end
|
28
app/models/bounced_mail_address.rb
Normal file
28
app/models/bounced_mail_address.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -33,70 +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)
|
||||
if discarded?
|
||||
raise StandardError, 'Force delete procedure cannot be scheduled while a domain is discarded'
|
||||
end
|
||||
|
||||
type == :fast_track ? force_delete_fast_track : force_delete_soft
|
||||
end
|
||||
|
||||
def add_force_delete_type(force_delete_type)
|
||||
self.force_delete_type = force_delete_type
|
||||
end
|
||||
|
||||
def force_delete_fast_track
|
||||
preserve_current_statuses_for_force_delete
|
||||
add_force_delete_statuses
|
||||
add_force_delete_type(:fast)
|
||||
self.force_delete_date = force_delete_fast_track_start_date + 1.day
|
||||
self.force_delete_start = Time.zone.today + 1.day
|
||||
stop_all_pending_actions
|
||||
allow_deletion
|
||||
save(validate: false)
|
||||
end
|
||||
|
||||
def force_delete_soft
|
||||
preserve_current_statuses_for_force_delete
|
||||
add_force_delete_statuses
|
||||
add_force_delete_type(:soft)
|
||||
calculate_soft_delete_date
|
||||
stop_all_pending_actions
|
||||
allow_deletion
|
||||
save(validate: false)
|
||||
end
|
||||
|
||||
def clear_force_delete_data
|
||||
self.force_delete_data = nil
|
||||
def schedule_force_delete(type: :fast_track, notify_by_email: false)
|
||||
Domains::ForceDelete::SetForceDelete.run(domain: self,
|
||||
type: type,
|
||||
notify_by_email: notify_by_email)
|
||||
end
|
||||
|
||||
def cancel_force_delete
|
||||
remove_force_delete_statuses
|
||||
restore_statuses_before_force_delete
|
||||
clear_force_delete_data
|
||||
self.force_delete_date = nil
|
||||
self.force_delete_start = nil
|
||||
save(validate: false)
|
||||
registrar.notifications.create!(text: I18n.t('force_delete_cancelled', domain_name: name))
|
||||
Domains::CancelForceDelete::CancelForceDelete.run(domain: self)
|
||||
end
|
||||
|
||||
def outzone_date
|
||||
|
@ -107,55 +51,4 @@ module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength
|
|||
(force_delete_date&.beginning_of_day || valid_to + Setting.expire_warning_period.days +
|
||||
Setting.redemption_grace_period.days)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def calculate_soft_delete_date
|
||||
years = (valid_to.to_date - Time.zone.today).to_i / 365
|
||||
soft_delete_dates(years) if years.positive?
|
||||
end
|
||||
|
||||
def soft_delete_dates(years)
|
||||
self.force_delete_start = valid_to - years.years
|
||||
self.force_delete_date = force_delete_start + Setting.expire_warning_period.days +
|
||||
Setting.redemption_grace_period.days
|
||||
end
|
||||
|
||||
def stop_all_pending_actions
|
||||
statuses.delete(DomainStatus::PENDING_UPDATE)
|
||||
statuses.delete(DomainStatus::PENDING_TRANSFER)
|
||||
statuses.delete(DomainStatus::PENDING_RENEW)
|
||||
statuses.delete(DomainStatus::PENDING_CREATE)
|
||||
end
|
||||
|
||||
def preserve_current_statuses_for_force_delete
|
||||
update(statuses_before_force_delete: statuses)
|
||||
end
|
||||
|
||||
def restore_statuses_before_force_delete
|
||||
self.statuses = statuses_before_force_delete
|
||||
self.statuses_before_force_delete = nil
|
||||
end
|
||||
|
||||
def add_force_delete_statuses
|
||||
self.statuses |= [DomainStatus::FORCE_DELETE,
|
||||
DomainStatus::SERVER_RENEW_PROHIBITED,
|
||||
DomainStatus::SERVER_TRANSFER_PROHIBITED]
|
||||
end
|
||||
|
||||
def remove_force_delete_statuses
|
||||
statuses.delete(DomainStatus::FORCE_DELETE)
|
||||
statuses.delete(DomainStatus::SERVER_RENEW_PROHIBITED)
|
||||
statuses.delete(DomainStatus::SERVER_TRANSFER_PROHIBITED)
|
||||
statuses.delete(DomainStatus::CLIENT_HOLD)
|
||||
end
|
||||
|
||||
def allow_deletion
|
||||
statuses.delete(DomainStatus::CLIENT_DELETE_PROHIBITED)
|
||||
statuses.delete(DomainStatus::SERVER_DELETE_PROHIBITED)
|
||||
end
|
||||
|
||||
def force_delete_fast_track_start_date
|
||||
Time.zone.today + Setting.expire_warning_period.days + Setting.redemption_grace_period.days
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -333,31 +333,6 @@ class Contact < ApplicationRecord
|
|||
Country.new(country_code)
|
||||
end
|
||||
|
||||
# TODO: refactor, it should not allow to destroy with normal destroy,
|
||||
# no need separate method
|
||||
# should use only in transaction
|
||||
def destroy_and_clean frame
|
||||
if linked?
|
||||
errors.add(:domains, :exist)
|
||||
return false
|
||||
end
|
||||
|
||||
legal_document_data = ::Deserializers::Xml::LegalDocument.new(frame).call
|
||||
|
||||
if legal_document_data
|
||||
|
||||
doc = LegalDocument.create(
|
||||
documentable_type: Contact,
|
||||
document_type: legal_document_data[:type],
|
||||
body: legal_document_data[:body]
|
||||
)
|
||||
self.legal_documents = [doc]
|
||||
self.legal_document_id = doc.id
|
||||
self.save
|
||||
end
|
||||
destroy
|
||||
end
|
||||
|
||||
def to_upcase_country_code
|
||||
self.ident_country_code = ident_country_code.upcase if ident_country_code
|
||||
self.country_code = country_code.upcase if country_code
|
||||
|
@ -372,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 ||= []
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -30,12 +30,13 @@ class Epp::Contact < Contact
|
|||
at
|
||||
end
|
||||
|
||||
def new(frame, registrar)
|
||||
def new(frame, registrar, epp: true)
|
||||
return super if frame.blank?
|
||||
|
||||
attrs = epp ? attrs_from(frame, new_record: true) : frame
|
||||
super(
|
||||
attrs_from(frame, new_record: true).merge(
|
||||
code: frame.css('id').text,
|
||||
attrs.merge(
|
||||
code: epp ? frame.css('id').text : frame[:id],
|
||||
registrar: registrar
|
||||
)
|
||||
)
|
||||
|
|
|
@ -417,7 +417,7 @@ class Epp::Domain < Domain
|
|||
if statuses.include?(x)
|
||||
to_destroy << x
|
||||
else
|
||||
add_epp_error('2303', 'status', x, [:domain_statuses, :not_found])
|
||||
add_epp_error('2303', 'status', x, %i[statuses not_found])
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -432,7 +432,7 @@ class Epp::Domain < Domain
|
|||
|
||||
frame.css('status').each do |x|
|
||||
unless DomainStatus::CLIENT_STATUSES.include?(x['s'])
|
||||
add_epp_error('2303', 'status', x['s'], [:domain_statuses, :not_found])
|
||||
add_epp_error('2303', 'status', x['s'], %i[statuses not_found])
|
||||
next
|
||||
end
|
||||
|
||||
|
@ -508,25 +508,6 @@ class Epp::Domain < Domain
|
|||
errors.empty? && super(at)
|
||||
end
|
||||
|
||||
def apply_pending_update!
|
||||
preclean_pendings
|
||||
user = ApiUser.find(pending_json['current_user_id'])
|
||||
frame = Nokogiri::XML(pending_json['frame'])
|
||||
|
||||
self.statuses.delete(DomainStatus::PENDING_UPDATE)
|
||||
self.upid = user.registrar.id if user.registrar
|
||||
self.up_date = Time.zone.now
|
||||
|
||||
return unless update(frame, user, false)
|
||||
clean_pendings!
|
||||
|
||||
save!
|
||||
|
||||
WhoisRecord.find_by(domain_id: id).save # need to reload model
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def apply_pending_delete!
|
||||
preclean_pendings
|
||||
statuses.delete(DomainStatus::PENDING_DELETE_CONFIRMATION)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -137,7 +137,8 @@ class Registrar < ApplicationRecord
|
|||
|
||||
def api_ip_white?(ip)
|
||||
return true unless Setting.api_ip_whitelist_enabled
|
||||
white_ips.api.pluck(:ipv4, :ipv6).flatten.include?(ip)
|
||||
|
||||
white_ips.api.include_ip?(ip)
|
||||
end
|
||||
|
||||
# Audit log is needed, therefore no raw SQL
|
||||
|
|
33
app/models/repp_api.rb
Normal file
33
app/models/repp_api.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -2,8 +2,8 @@ class WhiteIp < ApplicationRecord
|
|||
include Versions
|
||||
belongs_to :registrar
|
||||
|
||||
validates :ipv4, format: { with: /\A(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\z/, allow_blank: true }
|
||||
validates :ipv6, format: { with: /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/, allow_blank: true }
|
||||
validate :valid_ipv4?
|
||||
validate :valid_ipv6?
|
||||
|
||||
validate :validate_ipv4_and_ipv6
|
||||
def validate_ipv4_and_ipv6
|
||||
|
@ -11,6 +11,22 @@ class WhiteIp < ApplicationRecord
|
|||
errors.add(:base, I18n.t(:ipv4_or_ipv6_must_be_present))
|
||||
end
|
||||
|
||||
def valid_ipv4?
|
||||
return if ipv4.blank?
|
||||
|
||||
IPAddr.new(ipv4, Socket::AF_INET)
|
||||
rescue StandardError => _e
|
||||
errors.add(:ipv4, :invalid)
|
||||
end
|
||||
|
||||
def valid_ipv6?
|
||||
return if ipv6.blank?
|
||||
|
||||
IPAddr.new(ipv6, Socket::AF_INET6)
|
||||
rescue StandardError => _e
|
||||
errors.add(:ipv6, :invalid)
|
||||
end
|
||||
|
||||
API = 'api'
|
||||
REGISTRAR = 'registrar'
|
||||
INTERFACES = [API, REGISTRAR]
|
||||
|
@ -23,8 +39,37 @@ class WhiteIp < ApplicationRecord
|
|||
end
|
||||
|
||||
class << self
|
||||
# rubocop:disable Style/CaseEquality
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
def include_ip?(ip)
|
||||
where('ipv4 = :ip OR ipv6 = :ip', ip: ip).any?
|
||||
return false if ip.blank?
|
||||
|
||||
where(id: ids_including(ip)).any?
|
||||
end
|
||||
|
||||
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) }
|
||||
end
|
||||
if check_ip6(ip).present?
|
||||
ipv6 = select { |white_ip| IPAddr.new(white_ip.ipv6, Socket::AF_INET6) === check_ip6(ip) }
|
||||
end
|
||||
(ipv4 + ipv6).pluck(:id).flatten.uniq
|
||||
end
|
||||
# rubocop:enable Style/CaseEquality
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
|
||||
def check_ip4(ip)
|
||||
IPAddr.new(ip, Socket::AF_INET)
|
||||
rescue StandardError => _e
|
||||
nil
|
||||
end
|
||||
|
||||
def check_ip6(ip)
|
||||
IPAddr.new(ip, Socket::AF_INET6)
|
||||
rescue StandardError => _e
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue