Resolve merge errors

This commit is contained in:
Karl Erik Õunapuu 2020-09-02 16:25:34 +03:00
commit 73e9dd6870
817 changed files with 16875 additions and 17443 deletions

View file

@ -3,7 +3,7 @@ module Concerns::Contact::Transferable
included do
validates :auth_info, presence: true
after_initialize :generate_auth_info, if: 'new_record? && auth_info.blank?'
after_initialize :generate_auth_info, if: -> { new_record? && auth_info.blank? }
end
def transfer(new_registrar)

View file

@ -0,0 +1,44 @@
# frozen_string_literal: true
module Concerns
module Domain
module Disputable
extend ActiveSupport::Concern
included do
validate :validate_disputed
end
def mark_as_disputed
statuses.push(DomainStatus::DISPUTED) unless statuses.include?(DomainStatus::DISPUTED)
save
end
def unmark_as_disputed
statuses.delete_if { |status| status == DomainStatus::DISPUTED }
save
end
def in_disputed_list?
@in_disputed_list ||= Dispute.active.find_by(domain_name: name).present?
end
def disputed?
Dispute.active.where(domain_name: name).any?
end
def validate_disputed
return if persisted? || !in_disputed_list?
if reserved_pw.blank?
errors.add(:base, :required_parameter_missing_disputed)
return false
end
return if Dispute.valid_auth?(name, reserved_pw)
errors.add(:base, :invalid_auth_information_reserved)
end
end
end
end

View file

@ -1,32 +1,116 @@
module Concerns::Domain::ForceDelete
module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength
extend ActiveSupport::Concern
included do
store_accessor :force_delete_data,
:force_delete_type,
:contact_notification_sent_date,
:template_name
scope :notification_not_sent,
lambda {
where("(force_delete_data->>'contact_notification_sent_date') is null")
}
end
class_methods do
def force_delete_scheduled
where('force_delete_start <= ?', Time.zone.now)
end
end
def force_delete_scheduled?
statuses.include?(DomainStatus::FORCE_DELETE)
end
def schedule_force_delete
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
self.force_delete_date = Time.zone.today + Setting.redemption_grace_period.days + 1.day
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 cancel_force_delete
restore_statuses_before_force_delete
remove_force_delete_statuses
self.force_delete_date = nil
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
end
def cancel_force_delete
restore_statuses_before_force_delete
remove_force_delete_statuses
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))
end
def outzone_date
(force_delete_start || valid_to) + Setting.expire_warning_period.days
end
def purge_date
(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 + 1.day
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)
@ -35,7 +119,7 @@ module Concerns::Domain::ForceDelete
end
def preserve_current_statuses_for_force_delete
self.statuses_before_force_delete = statuses
self.statuses_before_force_delete = statuses.clone
end
def restore_statuses_before_force_delete
@ -47,25 +131,21 @@ module Concerns::Domain::ForceDelete
statuses << DomainStatus::FORCE_DELETE
statuses << DomainStatus::SERVER_RENEW_PROHIBITED
statuses << DomainStatus::SERVER_TRANSFER_PROHIBITED
statuses << DomainStatus::SERVER_UPDATE_PROHIBITED
statuses << DomainStatus::PENDING_DELETE
if (statuses & [DomainStatus::SERVER_HOLD, DomainStatus::CLIENT_HOLD]).empty?
statuses << DomainStatus::SERVER_MANUAL_INZONE
end
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::SERVER_UPDATE_PROHIBITED)
statuses.delete(DomainStatus::PENDING_DELETE)
statuses.delete(DomainStatus::SERVER_MANUAL_INZONE)
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

View file

@ -57,7 +57,8 @@ module Concerns::Domain::Transferable
def transfer_domain_contacts(new_registrar)
copied_ids = []
contacts.each do |contact|
domain_contacts.each do |dc|
contact = Contact.find(dc.contact_id)
next if copied_ids.include?(contact.id) || contact.registrar == new_registrar
if registrant_id_was == contact.id # registrant was copied previously, do not copy it again
@ -66,7 +67,11 @@ module Concerns::Domain::Transferable
oc = contact.transfer(new_registrar)
end
domain_contacts.where(contact_id: contact.id).update_all({ contact_id: oc.id }) # n+1 workaround
if domain_contacts.find_by(contact_id: oc.id, domain_id: id, type: dc.type).present?
dc.destroy
else
dc.update(contact_id: oc.id)
end
copied_ids << contact.id
end
end

View file

@ -0,0 +1,91 @@
module Concerns
module EmailVerifable
extend ActiveSupport::Concern
def email_verification
@email_verification ||= EmailAddressVerification.find_or_create_by(email: unicode_email,
domain: domain(email))
end
def billing_email_verification
return unless attribute_names.include?('billing_email')
@billing_email_verification ||= EmailAddressVerification
.find_or_create_by(email: unicode_billing_email,
domain: domain(billing_email))
end
class_methods do
def domain(email)
Mail::Address.new(email).domain&.downcase || 'not_found'
rescue Mail::Field::IncompleteParseError
'not_found'
end
def local(email)
Mail::Address.new(email).local&.downcase || email
rescue Mail::Field::IncompleteParseError
email
end
def punycode_to_unicode(email)
return email if domain(email) == 'not_found'
local = local(email)
domain = SimpleIDN.to_unicode(domain(email))
"#{local}@#{domain}"&.downcase
end
def unicode_to_punycode(email)
return email if domain(email) == 'not_found'
local = local(email)
domain = SimpleIDN.to_ascii(domain(email))
"#{local}@#{domain}"&.downcase
end
end
def unicode_billing_email
self.class.punycode_to_unicode(billing_email)
end
def unicode_email
self.class.punycode_to_unicode(email)
end
def domain(email)
SimpleIDN.to_unicode(self.class.domain(email))
end
def punycode_to_unicode(email)
self.class.punycode_to_unicode(email)
end
def correct_email_format
return if email.blank?
result = email_verification.verify
process_result(result: result, field: :email)
end
def correct_billing_email_format
return if email.blank?
result = billing_email_verification.verify
process_result(result: result, field: :billing_email)
end
# rubocop:disable Metrics/LineLength
def process_result(result:, field:)
case result[:errors].keys.first
when :smtp
errors.add(field, I18n.t('activerecord.errors.models.contact.attributes.email.email_smtp_check_error'))
when :mx
errors.add(field, I18n.t('activerecord.errors.models.contact.attributes.email.email_mx_check_error'))
when :regex
errors.add(field, I18n.t('activerecord.errors.models.contact.attributes.email.email_regex_check_error'))
end
end
# rubocop:enable Metrics/LineLength
end
end

View file

@ -20,7 +20,7 @@ module EppErrors
epp_errors << collect_parent_errors(attr, errors)
end
errors[:epp_errors] = epp_errors
errors.add(:epp_errors, epp_errors)
errors[:epp_errors].flatten!
end

View file

@ -0,0 +1,34 @@
module Concerns
module Invoice
module BookKeeping
extend ActiveSupport::Concern
def as_directo_json
invoice = ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(self))
invoice['customer'] = compose_directo_customer
invoice['issue_date'] = issue_date.strftime('%Y-%m-%d')
invoice['transaction_date'] = account_activity
.bank_transaction&.paid_at&.strftime('%Y-%m-%d')
invoice['language'] = buyer.language == 'en' ? 'ENG' : ''
invoice['invoice_lines'] = compose_directo_product
invoice
end
def compose_directo_product
[{ 'product_id': Setting.directo_receipt_product_name, 'description': order,
'quantity': 1, 'price': ActionController::Base.helpers.number_with_precision(
subtotal, precision: 2, separator: '.'
) }].as_json
end
def compose_directo_customer
{
'code': buyer.accounting_customer_code,
'destination': buyer_country_code,
'vat_reg_no': buyer_vat_no,
}.as_json
end
end
end
end

View file

@ -0,0 +1,34 @@
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

@ -0,0 +1,34 @@
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

@ -0,0 +1,31 @@
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)
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

@ -0,0 +1,128 @@
module Concerns
module Registrar
module BookKeeping
extend ActiveSupport::Concern
DOMAIN_TO_PRODUCT = { 'ee': '01EE', 'com.ee': '02COM', 'pri.ee': '03PRI',
'fie.ee': '04FIE', 'med.ee': '05MED' }.freeze
def monthly_summary(month:)
activities = monthly_activites(month)
return unless activities.any?
invoice = {
'number': 1,
'customer': compose_directo_customer,
'language': language == 'en' ? 'ENG' : '', 'currency': activities.first.currency,
'date': month.end_of_month.strftime('%Y-%m-%d')
}.as_json
invoice['invoice_lines'] = prepare_invoice_lines(month: month, activities: activities)
invoice
end
def prepare_invoice_lines(month:, activities:)
lines = []
lines << { 'description': title_for_summary(month) }
activities.each do |activity|
fetch_invoice_lines(activity, lines)
end
lines << prepayment_for_all(lines)
lines.as_json
end
def title_for_summary(date)
I18n.with_locale(language == 'en' ? 'en' : 'et') do
I18n.t('registrar.monthly_summary_title', date: I18n.l(date, format: '%B %Y'))
end
end
def fetch_invoice_lines(activity, lines)
price = load_price(activity)
if price.duration.include? 'year'
price.duration.to_i.times do |duration|
lines << new_monthly_invoice_line(activity: activity, duration: duration + 1).as_json
end
else
lines << new_monthly_invoice_line(activity: activity).as_json
end
end
def monthly_activites(month)
AccountActivity.where(account_id: account_ids)
.where(created_at: month.beginning_of_month..month.end_of_month)
.where(activity_type: [AccountActivity::CREATE, AccountActivity::RENEW])
end
def new_monthly_invoice_line(activity:, duration: nil)
price = load_price(activity)
line = {
'product_id': DOMAIN_TO_PRODUCT[price.zone_name.to_sym],
'quantity': 1,
'unit': language == 'en' ? 'pc' : 'tk',
}
finalize_invoice_line(line, price: price, duration: duration, activity: activity)
end
def finalize_invoice_line(line, price:, activity:, duration:)
yearly = price.duration.include?('year')
line['price'] = yearly ? (price.price.amount / price.duration.to_i) : price.price.amount
line['description'] = description_in_language(price: price, yearly: yearly)
if duration.present?
add_product_timeframe(line: line, activity: activity, duration: duration) if duration > 1
end
line
end
def add_product_timeframe(line:, activity:, duration:)
create_time = activity.created_at
line['start_date'] = (create_time + (duration - 1).year).end_of_month.strftime('%Y-%m-%d')
line['end_date'] = (create_time + (duration - 1).year + 1).end_of_month.strftime('%Y-%m-%d')
end
def description_in_language(price:, yearly:)
timeframe_string = yearly ? 'yearly' : 'monthly'
locale_string = "registrar.invoice_#{timeframe_string}_product_description"
I18n.with_locale(language == 'en' ? 'en' : 'et') do
I18n.t(locale_string, tld: ".#{price.zone_name}", length: price.duration.to_i)
end
end
def prepayment_for_all(lines)
total = 0
en = language == 'en'
lines.each { |l| total += l['quantity'].to_f * l['price'].to_f }
{
'product_id': Setting.directo_receipt_product_name,
'description': en ? 'Domains prepayment' : 'Domeenide ettemaks',
'quantity': -1,
'price': total,
'unit': en ? 'pc' : 'tk',
}
end
def compose_directo_customer
{
'code': accounting_customer_code,
'destination': address_country_code,
'vat_reg_no': vat_no,
}.as_json
end
def load_price(account_activity)
@pricelists ||= {}
return @pricelists[account_activity.price_id] if @pricelists.key? account_activity.price_id
@pricelists[account_activity.price_id] = account_activity.price
end
end
end
end

View file

@ -0,0 +1,16 @@
module Concerns
module Registrar
module LegalDoc
extend ActiveSupport::Concern
def legaldoc_mandatory?
!legaldoc_not_mandatory?
end
def legaldoc_not_mandatory?
setting = Setting.legal_document_is_mandatory
legaldoc_optout || !setting
end
end
end
end

View file

@ -0,0 +1,9 @@
module RemoveHold
extend ActiveSupport::Concern
def remove_hold(params)
xml = epp_xml.update(name: { value: params[:domain_name] },
rem: [status: { attrs: { s: 'clientHold' }, value: '' }])
current_user.request(xml)
end
end

View file

@ -1,10 +1,17 @@
# Papertrail concerns is mainly tested at country spec
module Versions
extend ActiveSupport::Concern
WITH_CHILDREN = %w[Domain Contact].freeze
included do
attr_accessor :version_loader
has_paper_trail class_name: "#{model_name}Version"
if WITH_CHILDREN.include?(model_name.name)
has_paper_trail versions: { class_name: "#{model_name}Version" },
meta: { children: :children_log }
else
has_paper_trail versions: { class_name: "#{model_name}Version" }
end
# add creator and updator
before_create :add_creator
@ -12,23 +19,25 @@ module Versions
before_update :add_updator
def add_creator
self.creator_str = ::PaperTrail.whodunnit
self.creator_str = ::PaperTrail.request.whodunnit
true
end
def add_updator
self.updator_str = ::PaperTrail.whodunnit
self.updator_str = ::PaperTrail.request.whodunnit
true
end
def creator
return nil if creator_str.blank?
creator = user_from_id_role_username creator_str
creator.present? ? creator : creator_str
end
def updator
return nil if updator_str.blank?
updator = user_from_id_role_username updator_str
updator.present? ? updator : updator_str
end
@ -45,25 +54,27 @@ module Versions
# callbacks
def touch_domain_version
domain.try(:touch_with_version)
domain.try(:touch)
end
def touch_domains_version
domains.each(&:touch_with_version)
domains.each(&:touch)
end
end
module ClassMethods
def all_versions_for(ids, time)
ver_klass = paper_trail_version_class
ver_klass = paper_trail.version_class
from_history = ver_klass.where(item_id: ids.to_a).
order(:item_id).
preceding(time + 1, true).
select("distinct on (item_id) #{ver_klass.table_name}.*").
map do |ver|
o = new(ver.object)
valid_columns = ver.item_type.constantize&.column_names
o = new(ver.object&.slice(*valid_columns))
o.version_loader = ver
ver.object_changes.to_h.each { |k, v| o.public_send("#{k}=", v[-1]) }
changes = ver.object_changes.to_h&.slice(*valid_columns)
changes.each { |k, v| o.public_send("#{k}=", v[-1]) }
o
end
not_in_history = where(id: (ids.to_a - from_history.map(&:id)))

View file

@ -0,0 +1,15 @@
module WhoisStatusPopulate
extend ActiveSupport::Concern
def generate_json(record, domain_status:)
h = HashWithIndifferentAccess.new(name: record.name, status: [domain_status])
return h if record.json.blank?
status_arr = (record.json['status'] ||= [])
return record.json if status_arr.include? domain_status
status_arr.push(domain_status)
record.json['status'] = status_arr
record.json
end
end

View file

@ -0,0 +1,74 @@
module Concerns
module Zone
module WhoisQueryable
extend ActiveSupport::Concern
included do
after_save :update_whois_record, if: :subzone?
after_destroy :update_whois_record
end
def subzone?
origin.include? '.'
end
def update_whois_record
UpdateWhoisRecordJob.enqueue origin, 'zone'
end
def generate_data
wr = Whois::Record.find_or_initialize_by(name: origin)
wr.json = generate_json
wr.save
end
def generate_json
data = {}.with_indifferent_access
[domain_vars, registrar_vars, registrant_vars].each do |h|
data.merge!(h)
end
data
end
# Take note - since this concern only used to zone whois queries, dnssec keys are set to
# empty array
def domain_vars
{ disclaimer: Setting.registry_whois_disclaimer, name: origin,
registered: created_at.try(:to_s, :iso8601), status: ['ok (paid and in zone)'],
changed: updated_at.try(:to_s, :iso8601), email: Setting.registry_email,
admin_contacts: [contact_vars], tech_contacts: [contact_vars],
nameservers: nameserver_vars, dnssec_keys: [], dnssec_changed: nil }
end
def registrar_vars
{ registrar: Setting.registry_juridical_name, registrar_website: Setting.registry_url,
registrar_phone: Setting.registry_phone }
end
def registrant_vars
{ registrant: Setting.registry_juridical_name, registrant_reg_no: Setting.registry_reg_no,
registrant_ident_country_code: Setting.registry_country_code, registrant_kind: 'org',
registrant_disclosed_attributes: %w[name email] }
end
def contact_vars
{ name: Setting.registry_invoice_contact, email: Setting.registry_email,
disclosed_attributes: %w[name email] }
end
def nameserver_vars
vars = []
return vars unless ns_records
parsed_ns = ns_records.gsub("\r", '').gsub("\n", '')
parsed_ns.split("#{origin}. IN NS ").each do |ns|
ns.delete_suffix! '.'
vars << ns if ns.match? Nameserver::HOSTNAME_REGEXP
end
vars
end
end
end
end