mirror of
https://github.com/internetee/registry.git
synced 2025-08-03 16:32:04 +02:00
Merge remote-tracking branch 'origin/master' into repp-domains
This commit is contained in:
commit
70759cb51b
24 changed files with 331 additions and 28 deletions
27
app/controllers/admin/mass_actions_controller.rb
Normal file
27
app/controllers/admin/mass_actions_controller.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class MassActionsController < BaseController
|
||||
before_action :authorize_admin
|
||||
|
||||
# GET /admin/mass_actions
|
||||
def index; end
|
||||
|
||||
# POST /admin/mass_actions
|
||||
def create
|
||||
res = MassAction.process(params[:mass_action], params[:entry_list].path)
|
||||
notice = if res
|
||||
"#{params[:mass_action]} completed for #{res[:ok]}.\n" \
|
||||
"Failed: #{res[:fail]}"
|
||||
else
|
||||
"Dataset integrity validation failed for #{params[:mass_action]}"
|
||||
end
|
||||
|
||||
redirect_to(admin_mass_actions_path, notice: notice)
|
||||
end
|
||||
|
||||
def authorize_admin
|
||||
authorize! :manage, :mass_actions
|
||||
end
|
||||
end
|
||||
end
|
|
@ -48,18 +48,25 @@ class Registrar
|
|||
parsed_response = JSON.parse(response.body, symbolize_names: true)
|
||||
|
||||
if response.code == '200'
|
||||
notices = [t('.replaced')]
|
||||
notices << "#{t('.affected_domains')}: " \
|
||||
"#{parsed_response[:data][:affected_domains].join(', ')}"
|
||||
|
||||
flash[:notice] = notices.join(', ')
|
||||
redirect_to registrar_domains_url
|
||||
redirect_to(registrar_domains_url,
|
||||
flash: { notice: compose_notice_message(parsed_response) })
|
||||
else
|
||||
@api_errors = parsed_response[:message]
|
||||
render file: 'registrar/bulk_change/new', locals: { active_tab: :nameserver }
|
||||
end
|
||||
end
|
||||
|
||||
def compose_notice_message(res)
|
||||
notices = ["#{t('.replaced')}. #{t('.affected_domains')}: " \
|
||||
"#{res[:data][:affected_domains].join(', ')}"]
|
||||
|
||||
if res[:data][:skipped_domains]
|
||||
notices << "#{t('.skipped_domains')}: #{res[:data][:skipped_domains].join(', ')}"
|
||||
end
|
||||
|
||||
notices.join(', ')
|
||||
end
|
||||
|
||||
def domain_list_from_csv
|
||||
return [] if params[:puny_file].blank?
|
||||
|
||||
|
|
|
@ -5,25 +5,31 @@ module Repp
|
|||
before_action :verify_nameserver_existance, only: %i[update]
|
||||
|
||||
def update
|
||||
domains = params[:data][:domains] || []
|
||||
affected = current_user.registrar
|
||||
.replace_nameservers(hostname,
|
||||
hostname_params[:data][:attributes],
|
||||
domains: domains)
|
||||
affected, errored = current_user.registrar
|
||||
.replace_nameservers(hostname,
|
||||
hostname_params[:data][:attributes],
|
||||
domains: domains_from_params)
|
||||
|
||||
render_success(data: data_format_for_success(affected))
|
||||
render_success(data: data_format_for_success(affected, errored))
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
handle_errors(e.record)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def data_format_for_success(affected_domains)
|
||||
def domains_from_params
|
||||
return [] unless params[:data][:domains]
|
||||
|
||||
params[:data][:domains].map(&:downcase)
|
||||
end
|
||||
|
||||
def data_format_for_success(affected_domains, errored_domains)
|
||||
{
|
||||
type: 'nameserver',
|
||||
id: params[:data][:attributes][:hostname],
|
||||
attributes: params[:data][:attributes],
|
||||
affected_domains: affected_domains,
|
||||
skipped_domains: errored_domains,
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@ module Domains
|
|||
boolean :notify_by_email,
|
||||
default: false,
|
||||
description: 'Do we need to send email notification'
|
||||
string :reason,
|
||||
default: nil,
|
||||
description: 'Which mail template to use explicitly'
|
||||
|
||||
validates :type, inclusion: { in: %i[fast_track soft] }
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ module Domains
|
|||
send_email
|
||||
domain.update(contact_notification_sent_date: Time.zone.today)
|
||||
else
|
||||
domain.update(template_name: domain.notification_template)
|
||||
domain.update(template_name: domain.notification_template(explicit: reason))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ class Ability
|
|||
can :destroy, :pending
|
||||
can :create, :zonefile
|
||||
can :access, :settings_menu
|
||||
can :manage, :mass_actions
|
||||
can :manage, BouncedMailAddress
|
||||
end
|
||||
|
||||
|
|
|
@ -19,7 +19,10 @@ module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength
|
|||
end
|
||||
end
|
||||
|
||||
def notification_template
|
||||
def notification_template(explicit: nil)
|
||||
reason = explicit&.downcase
|
||||
return reason if %w[invalid_email invalid_phone].include?(reason)
|
||||
|
||||
if contact_emails_verification_failed.present?
|
||||
'invalid_email'
|
||||
elsif registrant.org?
|
||||
|
@ -33,9 +36,8 @@ module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength
|
|||
statuses.include?(DomainStatus::FORCE_DELETE)
|
||||
end
|
||||
|
||||
def schedule_force_delete(type: :fast_track, notify_by_email: false)
|
||||
Domains::ForceDelete::SetForceDelete.run(domain: self,
|
||||
type: type,
|
||||
def schedule_force_delete(type: :fast_track, notify_by_email: false, reason: nil)
|
||||
Domains::ForceDelete::SetForceDelete.run(domain: self, type: type, reason: reason,
|
||||
notify_by_email: notify_by_email)
|
||||
end
|
||||
|
||||
|
|
42
app/models/mass_action.rb
Normal file
42
app/models/mass_action.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
class MassAction
|
||||
def self.process(action_type, entries)
|
||||
entries = CSV.read(entries, headers: true)
|
||||
case action_type
|
||||
when 'force_delete'
|
||||
process_force_delete(entries)
|
||||
else
|
||||
false
|
||||
end
|
||||
rescue StandardError
|
||||
false
|
||||
end
|
||||
|
||||
def self.process_force_delete(entries)
|
||||
return false unless force_delete_entries_valid?(entries)
|
||||
|
||||
apply_force_deletes(entries)
|
||||
end
|
||||
|
||||
def self.apply_force_deletes(entries)
|
||||
log = { ok: [], fail: [] }
|
||||
entries.each do |e|
|
||||
dn = Domain.find_by(name_puny: e['domain_name'])
|
||||
log[:fail] << e['domain_name'] and next unless dn
|
||||
|
||||
dn.schedule_force_delete(type: :soft, notify_by_email: true, reason: e['delete_reason'])
|
||||
|
||||
log[:ok] << dn.name
|
||||
end
|
||||
|
||||
log
|
||||
end
|
||||
|
||||
def self.force_delete_entries_valid?(entries)
|
||||
entries.each do |e|
|
||||
reasons = %w[ENTITY_BURIED INVALID_EMAIL INVALID_PHONE]
|
||||
return false unless e['domain_name'].present? && reasons.include?(e['delete_reason'])
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
end
|
|
@ -144,22 +144,33 @@ class Registrar < ApplicationRecord
|
|||
# Audit log is needed, therefore no raw SQL
|
||||
def replace_nameservers(hostname, new_attributes, domains: [])
|
||||
transaction do
|
||||
domain_scope = domains.dup
|
||||
domain_list = []
|
||||
failed_list = []
|
||||
|
||||
nameservers.where(hostname: hostname).find_each do |original_nameserver|
|
||||
next unless domains.include?(original_nameserver.domain.name_puny) || domains.empty?
|
||||
nameservers.where(hostname: hostname).find_each do |origin|
|
||||
idn = origin.domain.name
|
||||
puny = origin.domain.name_puny
|
||||
next unless domains.include?(idn) || domains.include?(puny) || domains.empty?
|
||||
|
||||
if origin.domain.nameservers.where(hostname: new_attributes[:hostname]).any?
|
||||
failed_list << idn
|
||||
next
|
||||
end
|
||||
|
||||
new_nameserver = Nameserver.new
|
||||
new_nameserver.domain = original_nameserver.domain
|
||||
new_nameserver.domain = origin.domain
|
||||
new_nameserver.attributes = new_attributes
|
||||
new_nameserver.save!
|
||||
|
||||
domain_list << original_nameserver.domain.name
|
||||
domain_scope.delete_if { |i| i == idn || i == puny }
|
||||
domain_list << idn
|
||||
|
||||
original_nameserver.destroy!
|
||||
origin.destroy!
|
||||
end
|
||||
|
||||
domain_list.uniq.sort
|
||||
self.domains.where(name: domain_list).find_each(&:update_whois_record) if domain_list.any?
|
||||
[domain_list.uniq.sort, (domain_scope + failed_list).uniq.sort]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
%li= link_to t('.blocked_domains'), admin_blocked_domains_path
|
||||
%li= link_to t('.reserved_domains'), admin_reserved_domains_path
|
||||
%li= link_to t('.disputed_domains'), admin_disputes_path
|
||||
%li= link_to t('.bulk_actions'), admin_mass_actions_path
|
||||
%li= link_to t('.bounced_email_addresses'), admin_bounced_mail_addresses_path
|
||||
%li= link_to t('.epp_log'), admin_epp_logs_path(created_after: 'today')
|
||||
%li= link_to t('.repp_log'), admin_repp_logs_path(created_after: 'today')
|
||||
|
|
19
app/views/admin/mass_actions/index.html.erb
Normal file
19
app/views/admin/mass_actions/index.html.erb
Normal file
|
@ -0,0 +1,19 @@
|
|||
<div class="page-header">
|
||||
<h1>Bulk actions</h1>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Bulk Domain Force Delete</div>
|
||||
<div class="panel-body">
|
||||
<p>Triggers <b>soft</b> force delete procedure for uploaded domain list. List must be in <b>CSV</b> format. First row of the CSV file must contain column headings with <b>domain_name</b> for the first and <b>delete_reason</b> for the second column. Each domain entry must be on separate line. Domain names are expected to be in punycode format, valid reasons are listed below.</p>
|
||||
<p>Allowed delete reasons: <b>ENTITY_BURIED</b> | <b>INVALID_PHONE</b> | <b>INVALID_EMAIL</b></p>
|
||||
<%= form_tag admin_mass_actions_path, multipart: true, method: :post do %>
|
||||
<%= label_tag :entry_list %>
|
||||
<%= file_field_tag :entry_list, required: true, accept: 'text/csv' %>
|
||||
<%= hidden_field_tag :mass_action, 'force_delete' %>
|
||||
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
|
||||
<br>
|
||||
<%= submit_tag "Start force delete process", class: 'btn btn-danger', id: 'fd_submit' %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,47 @@
|
|||
<p>Lugupeetud domeeni <%= @domain.name %> registreerija/halduskontakt</p>
|
||||
|
||||
<p>Eesti Interneti Sihtasutusele (EIS) on saanud teatavaks, et domeeni <%= @domain.name %> kontakti(de) telefoni number või numbrid on puudulikud.</p>
|
||||
|
||||
<p>Et see olukord on vastuolus .ee <a href='https://www.internet.ee/domains/ee-domain-regulation'>domeenireeglitega</a> algatas EIS <%= @delete_period_length %> päeva pikkuse kustutusmenetluse. Menetluse käigus on domeen <%= @expire_warning_period %> esimest päeva internetis kättesaadav.</p>
|
||||
|
||||
<p>Andmete parandamiseks pöörduge palun oma registripidaja <%= @registrar.name %> poole või isiklike ja oma ettevõtte andmete puhul <a href="https://registrant.internet.ee/">registreerija portaali</a>.</p>
|
||||
|
||||
<p>Kui kontaktandmed ei ole <%= @delete_period_length %> päeva jooksul parandatud, läheb domeen <%= @domain.name %> <%= @domain.force_delete_date %> domeenioksjonile <a href="https://auction.internet.ee">.ee oksjonikeskkonda</a>. Juhul kui domeenile <%= @domain.name %> ei tehta oksjonil 24h möödudes pakkumist, domeen vabaneb ja on registreerimiseks vabalt kättesaadav kõigile huvilistele. Muude võimalike oksjoni tulemuste kohta loe <a href="https://www.internet.ee/domeenid/domeenide-oksjonikeskkonna-kasutajatingimused#3-oksjonikeskkonna-enampakkumisel-osalemise-tingimused">siit</a>.</p>
|
||||
|
||||
<p>Lisaküsimuste korral võtke palun ühendust oma registripidajaga:</p>
|
||||
<%= render 'mailers/shared/registrar/registrar.et.html', registrar: @registrar %>
|
||||
|
||||
<%= render 'mailers/shared/signatures/signature.et.html' %>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Dear registrant/administrative contact of .ee domain,</p>
|
||||
|
||||
<p>Estonian Internet Foundation has learned that contact(s) phone number data of the domain <%= @domain.name %> are invalid.</p>
|
||||
|
||||
<p>Since this is a violation of <a href='https://www.internet.ee/domains/ee-domain-regulation'>Estonian domain regulations</a>, <%= @delete_period_length %>-day deletion process has started for the <%= @domain.name %> domain. For the first <%= @expire_warning_period %> days the domain will remain available on the Internet during the deletion process.</p>
|
||||
|
||||
<p>Please, contact your registrar <%= @registrar.name %> with updated contact data, or in case of your personal or business data use <a href="https://registrant.internet.ee/">.ee portal for registrants</a></p>
|
||||
|
||||
<p>If the data is not fixed within <%= @delete_period_length %> days, the domain <%= @domain.name %> will go to domain auction on <%= @domain.force_delete_date %> in the <a href="https://auction.internet.ee">.ee auction environment</a>. If no offer is made for the domain <%= @domain.name %> at auction within 24 hours, the domain will be released and made freely available for registration to anyone interested on a first-come, first-served basis. Read more about other potential auction results <a href="https://www.internet.ee/domains/auction-environment-user-agreement#3-terms-and-conditions-for-participation-in-the-auction-of-the-auction-environment">here</a>.</p>
|
||||
|
||||
<p>Should you have additional questions, please contact your registrar:</p>
|
||||
<%= render 'mailers/shared/registrar/registrar.en.html', registrar: @registrar %>
|
||||
|
||||
<%= render 'mailers/shared/signatures/signature.en.html' %>
|
||||
<hr>
|
||||
|
||||
<p>Уважаемый регистрант/административный контакт домена .ee</p>
|
||||
|
||||
<p>Целевому учреждению Eesti Internet (EIS) стало известно, что контактные данные домена <%= @domain.name %> неверны - телефонные номера.</p>
|
||||
|
||||
<p>Так как это является нарушением <a href='https://www.internet.ee/domains/ee-domain-regulation'>Правил домена .ee</a>, <%= @delete_period_length %>-дневный процесс удаления начат для доменного имени <%= @domain.name %>. В течение первых <%= @expire_warning_period %> дней домен будет доступен в интернете.</p>
|
||||
|
||||
<p>Для уточнения контактных данных, пожалуйста, свяжитесь с регистратором <%= @registrar.name %>, либо воспользуйтесь <a href="https://registrant.internet.ee/">порталом для регистрантов</a></p>
|
||||
|
||||
<p>Если контактные данные не будут исправлены в течение <%= @delete_period_length %> дней, домен <%= @domain.name %> отправится <%= @domain.force_delete_date %> на доменный аукцион в <a href="https://auction.internet.ee">аукционной среде.ee</a>. Если в течение 24 часов в отношении домена <%= @domain.name %> е поступит предложений, домен освободится и станет доступным для всех желающих по принципу «кто раньше». О других возможных результатах аукциона читайте <a href="https://www.internet.ee/domains/auction-environment-user-agreement#3-terms-and-conditions-for-participation-in-the-auction-of-the-auction-environment">здесь</a>.</p>
|
||||
|
||||
<p>В случае возникновения дополнительных вопросов свяжитесь, пожалуйста, со своим регистратором:
|
||||
<%= render 'mailers/shared/registrar/registrar.ru.html', registrar: @registrar %></p>
|
||||
|
||||
<%= render 'mailers/shared/signatures/signature.ru.html' %>
|
|
@ -0,0 +1,47 @@
|
|||
<p>Lugupeetud domeeni <%= @domain.name %> registreerija/halduskontakt</p>
|
||||
|
||||
<p>Eesti Interneti Sihtasutusele (EIS) on saanud teatavaks, et domeeni <%= @domain.name %> kontakti(de) telefoni number või numbrid on puudulikud.</p>
|
||||
|
||||
<p>Et see olukord on vastuolus .ee <a href='https://www.internet.ee/domains/ee-domain-regulation'>domeenireeglitega</a> algatas EIS <%= @delete_period_length %> päeva pikkuse kustutusmenetluse. Menetluse käigus on domeen <%= @expire_warning_period %> esimest päeva internetis kättesaadav.</p>
|
||||
|
||||
<p>Andmete parandamiseks pöörduge palun oma registripidaja <%= @registrar.name %> poole või isiklike ja oma ettevõtte andmete puhul <a href="https://registrant.internet.ee/">registreerija portaali</a>.</p>
|
||||
|
||||
<p>Kui kontaktandmed ei ole <%= @delete_period_length %> päeva jooksul parandatud, läheb domeen <%= @domain.name %> <%= @domain.force_delete_date %> domeenioksjonile <a href="https://auction.internet.ee">.ee oksjonikeskkonda</a>. Juhul kui domeenile <%= @domain.name %> ei tehta oksjonil 24h möödudes pakkumist, domeen vabaneb ja on registreerimiseks vabalt kättesaadav kõigile huvilistele. Muude võimalike oksjoni tulemuste kohta loe <a href="https://www.internet.ee/domeenid/domeenide-oksjonikeskkonna-kasutajatingimused#3-oksjonikeskkonna-enampakkumisel-osalemise-tingimused">siit</a>.</p>
|
||||
|
||||
<p>Lisaküsimuste korral võtke palun ühendust oma registripidajaga:</p>
|
||||
<%= render 'mailers/shared/registrar/registrar.et.html', registrar: @registrar %>
|
||||
|
||||
<%= render 'mailers/shared/signatures/signature.et.html' %>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Dear registrant/administrative contact of .ee domain,</p>
|
||||
|
||||
<p>Estonian Internet Foundation has learned that contact(s) phone number data of the domain <%= @domain.name %> are invalid.</p>
|
||||
|
||||
<p>Since this is a violation of <a href='https://www.internet.ee/domains/ee-domain-regulation'>Estonian domain regulations</a>, <%= @delete_period_length %>-day deletion process has started for the <%= @domain.name %> domain. For the first <%= @expire_warning_period %> days the domain will remain available on the Internet during the deletion process.</p>
|
||||
|
||||
<p>Please, contact your registrar <%= @registrar.name %> with updated contact data, or in case of your personal or business data use <a href="https://registrant.internet.ee/">.ee portal for registrants</a></p>
|
||||
|
||||
<p>If the data is not fixed within <%= @delete_period_length %> days, the domain <%= @domain.name %> will go to domain auction on <%= @domain.force_delete_date %> in the <a href="https://auction.internet.ee">.ee auction environment</a>. If no offer is made for the domain <%= @domain.name %> at auction within 24 hours, the domain will be released and made freely available for registration to anyone interested on a first-come, first-served basis. Read more about other potential auction results <a href="https://www.internet.ee/domains/auction-environment-user-agreement#3-terms-and-conditions-for-participation-in-the-auction-of-the-auction-environment">here</a>.</p>
|
||||
|
||||
<p>Should you have additional questions, please contact your registrar:</p>
|
||||
<%= render 'mailers/shared/registrar/registrar.en.html', registrar: @registrar %>
|
||||
|
||||
<%= render 'mailers/shared/signatures/signature.en.html' %>
|
||||
<hr>
|
||||
|
||||
<p>Уважаемый регистрант/административный контакт домена .ee</p>
|
||||
|
||||
<p>Целевому учреждению Eesti Internet (EIS) стало известно, что контактные данные домена <%= @domain.name %> неверны - телефонные номера.</p>
|
||||
|
||||
<p>Так как это является нарушением <a href='https://www.internet.ee/domains/ee-domain-regulation'>Правил домена .ee</a>, <%= @delete_period_length %>-дневный процесс удаления начат для доменного имени <%= @domain.name %>. В течение первых <%= @expire_warning_period %> дней домен будет доступен в интернете.</p>
|
||||
|
||||
<p>Для уточнения контактных данных, пожалуйста, свяжитесь с регистратором <%= @registrar.name %>, либо воспользуйтесь <a href="https://registrant.internet.ee/">порталом для регистрантов</a></p>
|
||||
|
||||
<p>Если контактные данные не будут исправлены в течение <%= @delete_period_length %> дней, домен <%= @domain.name %> отправится <%= @domain.force_delete_date %> на доменный аукцион в <a href="https://auction.internet.ee">аукционной среде.ee</a>. Если в течение 24 часов в отношении домена <%= @domain.name %> е поступит предложений, домен освободится и станет доступным для всех желающих по принципу «кто раньше». О других возможных результатах аукциона читайте <a href="https://www.internet.ee/domains/auction-environment-user-agreement#3-terms-and-conditions-for-participation-in-the-auction-of-the-auction-environment">здесь</a>.</p>
|
||||
|
||||
<p>В случае возникновения дополнительных вопросов свяжитесь, пожалуйста, со своим регистратором:
|
||||
<%= render 'mailers/shared/registrar/registrar.ru.html', registrar: @registrar %></p>
|
||||
|
||||
<%= render 'mailers/shared/signatures/signature.ru.html' %>
|
Loading…
Add table
Add a link
Reference in a new issue