mirror of
https://github.com/internetee/registry.git
synced 2025-06-06 12:47:29 +02:00
Merge branch 'master' of https://github.com/internetee/registry into 1804-upgrade-ui-tests-for-admin-portal-users
This commit is contained in:
commit
54a8c65c27
28 changed files with 380 additions and 50 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -1,6 +1,14 @@
|
|||
14.01.2021
|
||||
* Fixed IDN and punycode support for REPP domain transfer_info request [#1801](https://github.com/internetee/registry/issues/1801)
|
||||
|
||||
06.01.2021
|
||||
* IMproved tests whois update for bulk nameserver change [#1739](https://github.com/internetee/registry/issues/1739)
|
||||
* Bulk ForceDelete funcionality in admin [#1177](https://github.com/internetee/registry/issues/1177)
|
||||
* Reverted Nokogiri bump due to dependency conflicts in production [#1787](https://github.com/internetee/registry/pull/1787)
|
||||
|
||||
05.01.2021
|
||||
* Fixed ok/inactive bug together with disclosed contact atribute handling [#1786](https://github.com/internetee/registry/pull/1786)
|
||||
* Ident data to simplified domain list in registrant APO to help with sorting and filtering [#1783](https://github.com/internetee/registry/pull/1783)
|
||||
* Fixed ok/inactive bug together with disclosed contact attribute handling [#1786](https://github.com/internetee/registry/pull/1786)
|
||||
* Ident data to simplified domain list in registrant API to help with sorting and filtering [#1783](https://github.com/internetee/registry/pull/1783)
|
||||
* Bumped Nokogiri to 1.11.0 [#1785](https://github.com/internetee/registry/pull/1785)
|
||||
|
||||
23.12.2020
|
||||
|
|
|
@ -264,7 +264,7 @@ GEM
|
|||
mime-types-data (3.2020.0512)
|
||||
mimemagic (0.3.5)
|
||||
mini_mime (1.0.2)
|
||||
mini_portile2 (2.5.0)
|
||||
mini_portile2 (2.4.0)
|
||||
minitest (5.14.2)
|
||||
monetize (1.9.4)
|
||||
money (~> 6.12)
|
||||
|
@ -281,9 +281,8 @@ GEM
|
|||
ruby2_keywords (~> 0.0.1)
|
||||
netrc (0.11.0)
|
||||
nio4r (2.5.4)
|
||||
nokogiri (1.11.0)
|
||||
mini_portile2 (~> 2.5.0)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.10.10)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
nori (2.6.0)
|
||||
omniauth (1.9.1)
|
||||
hashie (>= 3.4.6)
|
||||
|
@ -321,7 +320,6 @@ GEM
|
|||
erubis
|
||||
que (~> 0.8)
|
||||
sinatra
|
||||
racc (1.5.2)
|
||||
rack (2.2.3)
|
||||
rack-oauth2 (1.16.0)
|
||||
activesupport
|
||||
|
|
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?
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Repp
|
||||
module V1
|
||||
class BaseController < ActionController::API
|
||||
rescue_from ActiveRecord::RecordNotFound, with: :not_found_error
|
||||
around_action :log_request
|
||||
before_action :authenticate_user
|
||||
before_action :validate_webclient_ca
|
||||
before_action :check_ip_restriction
|
||||
|
@ -9,21 +9,31 @@ module Repp
|
|||
|
||||
before_action :set_paper_trail_whodunnit
|
||||
|
||||
rescue_from ActionController::ParameterMissing do |exception|
|
||||
render json: { code: 2003, message: exception }, status: :bad_request
|
||||
private
|
||||
|
||||
def log_request
|
||||
yield
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
@response = { code: 2303, message: 'Object does not exist' }
|
||||
render(json: @response, status: :not_found)
|
||||
rescue ActionController::ParameterMissing => e
|
||||
@response = { code: 2003, message: e }
|
||||
render(json: @response, status: :bad_request)
|
||||
ensure
|
||||
create_repp_log
|
||||
end
|
||||
|
||||
after_action do
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
def create_repp_log
|
||||
ApiLog::ReppLog.create(
|
||||
request_path: request.path, request_method: request.request_method,
|
||||
request_params: request.params.except('route_info').to_json, uuid: request.try(:uuid),
|
||||
response: @response.to_json, response_code: status, ip: request.ip,
|
||||
response: @response.to_json, response_code: response.status, ip: request.ip,
|
||||
api_user_name: current_user.try(:username),
|
||||
api_user_registrar: current_user.try(:registrar).try(:to_s)
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
|
||||
def set_paper_trail_whodunnit
|
||||
::PaperTrail.request.whodunnit = current_user
|
||||
|
@ -120,11 +130,6 @@ module Repp
|
|||
|
||||
render(json: @response, status: :unauthorized)
|
||||
end
|
||||
|
||||
def not_found_error
|
||||
@response = { code: 2303, message: 'Object does not exist' }
|
||||
render(json: @response, status: :not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -68,9 +68,7 @@ module Repp
|
|||
|
||||
def set_authorized_domain
|
||||
@epp_errors ||= []
|
||||
h = {}
|
||||
h[transfer_info_params[:id].match?(/\A[0-9]+\z/) ? :id : :name] = transfer_info_params[:id]
|
||||
@domain = Domain.find_by!(h)
|
||||
@domain = domain_from_url_hash
|
||||
|
||||
return if @domain.transfer_code.eql?(request.headers['Auth-Code'])
|
||||
|
||||
|
@ -78,6 +76,13 @@ module Repp
|
|||
handle_errors
|
||||
end
|
||||
|
||||
def domain_from_url_hash
|
||||
entry = transfer_info_params[:id]
|
||||
return Domain.find(entry) if entry.match?(/\A[0-9]+\z/)
|
||||
|
||||
Domain.find_by!('name = ? OR name_puny = ?', entry, entry)
|
||||
end
|
||||
|
||||
def limit
|
||||
index_params[:limit] || 200
|
||||
end
|
||||
|
|
|
@ -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' %>
|
|
@ -14,6 +14,7 @@ en:
|
|||
blocked_domains: Blocked domains
|
||||
reserved_domains: Reserved domains
|
||||
disputed_domains: Disputed domains
|
||||
bulk_actions: Bulk actions
|
||||
bounced_email_addresses: Bounced emails
|
||||
epp_log: EPP log
|
||||
repp_log: REPP log
|
||||
|
|
|
@ -4,3 +4,4 @@ en:
|
|||
update:
|
||||
replaced: Nameserver have been successfully replaced
|
||||
affected_domains: Affected domains
|
||||
skipped_domains: Untouched domains
|
||||
|
|
|
@ -322,6 +322,7 @@ Rails.application.routes.draw do
|
|||
resources :delayed_jobs
|
||||
resources :epp_logs
|
||||
resources :repp_logs
|
||||
resources :mass_actions, only: %i[index create]
|
||||
resources :bounced_mail_addresses, only: %i[index show destroy]
|
||||
|
||||
authenticate :admin_user do
|
||||
|
|
2
test/fixtures/files/mass_actions/invalid_mass_force_delete_list.csv
vendored
Normal file
2
test/fixtures/files/mass_actions/invalid_mass_force_delete_list.csv
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
domain_name,delete_reason
|
||||
sh\á;[]c'
|
|
5
test/fixtures/files/mass_actions/valid_mass_force_delete_list.csv
vendored
Normal file
5
test/fixtures/files/mass_actions/valid_mass_force_delete_list.csv
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
domain_name,delete_reason
|
||||
shop.test,ENTITY_BURIED
|
||||
airport.test,INVALID_PHONE
|
||||
library.test,INVALID_EMAIL
|
||||
nonexistant.test,ENTITY_BURIED
|
|
2
test/fixtures/files/valid_domains_for_ns_replacement.csv
vendored
Normal file
2
test/fixtures/files/valid_domains_for_ns_replacement.csv
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
domain_name
|
||||
shop.test
|
|
|
@ -67,7 +67,8 @@ class APINameserversPutTest < ApplicationIntegrationTest
|
|||
attributes: { hostname: 'ns55.bestnames.test',
|
||||
ipv4: ['192.0.2.55'],
|
||||
ipv6: ['2001:db8::55'] },
|
||||
affected_domains: ["airport.test", "shop.test"] }}),
|
||||
affected_domains: ["airport.test", "shop.test"],
|
||||
skipped_domains: [] }}),
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
|
|
|
@ -37,4 +37,17 @@ class ReppV1DomainsTransferInfoTest < ActionDispatch::IntegrationTest
|
|||
assert_equal 'Authorization error', json[:message]
|
||||
assert_empty json[:data]
|
||||
end
|
||||
|
||||
def test_processes_puny_domains
|
||||
@domain.update(name_puny: 'xn--prototp-s2aa.ee')
|
||||
|
||||
headers = @auth_headers
|
||||
headers['Auth-Code'] = @domain.transfer_code
|
||||
|
||||
get "/repp/v1/domains/xn--prototp-s2aa.ee/transfer_info", headers: headers
|
||||
json = JSON.parse(response.body, symbolize_names: true)
|
||||
|
||||
assert_response :ok
|
||||
assert_equal 1000, json[:code]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,7 +10,7 @@ class ReplaceNameserversTest < ActiveSupport::TestCase
|
|||
ipv6: '2001:db8::2' }
|
||||
result = @registrar.replace_nameservers('ns1.bestnames.test', new_attributes)
|
||||
|
||||
assert_equal(["airport.test", "shop.test"], result)
|
||||
assert_equal([["airport.test", "shop.test"], []], result)
|
||||
end
|
||||
|
||||
def test_replace_nameservers_in_bulk_returns_empty_array_for_non_existent_base_nameserver
|
||||
|
@ -18,6 +18,22 @@ class ReplaceNameserversTest < ActiveSupport::TestCase
|
|||
ipv6: '2001:db8::2' }
|
||||
result = @registrar.replace_nameservers('ns3.bestnames.test', new_attributes)
|
||||
|
||||
assert_equal([], result)
|
||||
assert_equal([[], []], result)
|
||||
end
|
||||
|
||||
def test_replace_nameserver_in_bulk_respects_domain_limit_scope
|
||||
eligible_domain = domains(:shop)
|
||||
unscoped_domain = domains(:airport)
|
||||
|
||||
new_attributes = { hostname: 'ns-updated1.bestnames.test', ipv4: '192.0.3.1',
|
||||
ipv6: '2001:db8::2' }
|
||||
|
||||
result = @registrar.replace_nameservers('ns1.bestnames.test', new_attributes, domains: ['shop.test'])
|
||||
assert_equal([["shop.test"], []], result)
|
||||
|
||||
unscoped_domain.reload
|
||||
eligible_domain.reload
|
||||
assert eligible_domain.nameservers.where(hostname: 'ns1.bestnames.test').empty?
|
||||
assert unscoped_domain.nameservers.where(hostname: 'ns1.bestnames.test').any?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
require 'application_system_test_case'
|
||||
require 'test_helper'
|
||||
|
||||
class AdminAreaMassActionsForceDeleteTest < ApplicationSystemTestCase
|
||||
def setup
|
||||
sign_in users(:admin)
|
||||
end
|
||||
|
||||
def test_processes_uploaded_valid_csv
|
||||
visit admin_mass_actions_path
|
||||
|
||||
attach_file('entry_list', Rails.root.join('test', 'fixtures', 'files', 'mass_actions', 'valid_mass_force_delete_list.csv').to_s)
|
||||
click_link_or_button 'Start force delete process'
|
||||
assert_text 'force_delete completed for ["shop.test", "airport.test", "library.test"]. Failed: ["nonexistant.test"]'
|
||||
end
|
||||
|
||||
def test_processes_uploaded_invalid_csv
|
||||
visit admin_mass_actions_path
|
||||
|
||||
attach_file(:entry_list, Rails.root.join('test', 'fixtures', 'files', 'mass_actions', 'invalid_mass_force_delete_list.csv').to_s)
|
||||
click_link_or_button 'Start force delete process'
|
||||
assert_text 'Dataset integrity validation failed for force_delete'
|
||||
end
|
||||
end
|
|
@ -18,7 +18,8 @@ class RegistrarAreaNameserverBulkChangeTest < ApplicationSystemTestCase
|
|||
.to_return(body: { data: {
|
||||
type: 'nameserver',
|
||||
id: 'new-ns.bestnames.test',
|
||||
affected_domains: ["airport.test", "shop.test"]
|
||||
affected_domains: ["airport.test", "shop.test"],
|
||||
skipped_domains: []
|
||||
}
|
||||
}.to_json, status: 200)
|
||||
|
||||
|
@ -59,4 +60,38 @@ class RegistrarAreaNameserverBulkChangeTest < ApplicationSystemTestCase
|
|||
assert_field 'ipv4', with: 'ipv4'
|
||||
assert_field 'ipv6', with: 'ipv6'
|
||||
end
|
||||
|
||||
def test_replaces_nameservers_only_for_scoped_domains
|
||||
request_body = { data: { type: 'nameserver',
|
||||
id: 'ns1.bestnames.test',
|
||||
domains: ['shop.test'],
|
||||
attributes: { hostname: 'new-ns.bestnames.test',
|
||||
ipv4: %w[192.0.2.55 192.0.2.56],
|
||||
ipv6: %w[2001:db8::55 2001:db8::56] } } }
|
||||
request_stub = stub_request(:put, /registrar\/nameservers/).with(body: request_body,
|
||||
headers: { 'Content-type' => Mime[:json] },
|
||||
basic_auth: ['test_goodnames', 'testtest'])
|
||||
.to_return(body: { data: {
|
||||
type: 'nameserver',
|
||||
id: 'new-ns.bestnames.test',
|
||||
affected_domains: ["shop.test"],
|
||||
skipped_domains: []}}.to_json, status: 200)
|
||||
|
||||
visit registrar_domains_url
|
||||
click_link 'Bulk change'
|
||||
click_link 'Nameserver'
|
||||
|
||||
fill_in 'Old hostname', with: 'ns1.bestnames.test'
|
||||
fill_in 'New hostname', with: 'new-ns.bestnames.test'
|
||||
fill_in 'ipv4', with: "192.0.2.55\n192.0.2.56"
|
||||
fill_in 'ipv6', with: "2001:db8::55\n2001:db8::56"
|
||||
attach_file :puny_file, Rails.root.join('test', 'fixtures', 'files', 'valid_domains_for_ns_replacement.csv').to_s
|
||||
|
||||
click_on 'Replace nameserver'
|
||||
|
||||
assert_requested request_stub
|
||||
assert_current_path registrar_domains_path
|
||||
assert_text 'Nameserver have been successfully replaced'
|
||||
assert_text 'Affected domains: shop.test'
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue