mirror of
https://github.com/internetee/registry.git
synced 2025-06-11 15:14:47 +02:00
parent
f7c2b25a66
commit
228078a84e
30 changed files with 474 additions and 66 deletions
|
@ -59,5 +59,6 @@ module Repp
|
||||||
mount Repp::AccountV1
|
mount Repp::AccountV1
|
||||||
mount Repp::DomainTransfersV1
|
mount Repp::DomainTransfersV1
|
||||||
mount Repp::NameserversV1
|
mount Repp::NameserversV1
|
||||||
|
mount Repp::DomainContactsV1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
35
app/api/repp/domain_contacts_v1.rb
Normal file
35
app/api/repp/domain_contacts_v1.rb
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
module Repp
|
||||||
|
class DomainContactsV1 < Grape::API
|
||||||
|
version 'v1', using: :path
|
||||||
|
|
||||||
|
resource :domains do
|
||||||
|
resource :contacts do
|
||||||
|
patch '/' do
|
||||||
|
predecessor = current_user.registrar.contacts.find_by(code: params[:predecessor])
|
||||||
|
successor = current_user.registrar.contacts.find_by(code: params[:successor])
|
||||||
|
|
||||||
|
unless predecessor
|
||||||
|
error!({ error: { type: 'invalid_request_error',
|
||||||
|
param: 'predecessor',
|
||||||
|
message: "No such contact: #{params[:predecessor]}" } }, :bad_request)
|
||||||
|
end
|
||||||
|
|
||||||
|
unless successor
|
||||||
|
error!({ error: { type: 'invalid_request_error',
|
||||||
|
param: 'successor',
|
||||||
|
message: "No such contact: #{params[:successor]}" } }, :bad_request)
|
||||||
|
end
|
||||||
|
|
||||||
|
if predecessor == successor
|
||||||
|
error!({ error: { type: 'invalid_request_error',
|
||||||
|
message: 'Successor contact must be different from predecessor' } },
|
||||||
|
:bad_request)
|
||||||
|
end
|
||||||
|
|
||||||
|
affected_domains, skipped_domains = TechDomainContact.replace(predecessor, successor)
|
||||||
|
@response = { affected_domains: affected_domains, skipped_domains: skipped_domains }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
20
app/controllers/registrar/bulk_change_controller.rb
Normal file
20
app/controllers/registrar/bulk_change_controller.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
class Registrar
|
||||||
|
class BulkChangeController < DeppController
|
||||||
|
helper_method :available_contacts
|
||||||
|
|
||||||
|
def new
|
||||||
|
authorize! :manage, :repp
|
||||||
|
render file: 'registrar/bulk_change/new', locals: { active_tab: default_tab }
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def available_contacts
|
||||||
|
current_user.registrar.contacts.order(:name).pluck(:name, :code)
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_tab
|
||||||
|
:technical_contact
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,9 +1,5 @@
|
||||||
class Registrar
|
class Registrar
|
||||||
class RegistrarNameserversController < DeppController
|
class NameserversController < BulkChangeController
|
||||||
def edit
|
|
||||||
authorize! :manage, :repp
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
def update
|
||||||
authorize! :manage, :repp
|
authorize! :manage, :repp
|
||||||
|
|
||||||
|
@ -52,7 +48,7 @@ class Registrar
|
||||||
redirect_to registrar_domains_url
|
redirect_to registrar_domains_url
|
||||||
else
|
else
|
||||||
@api_errors = parsed_response[:errors]
|
@api_errors = parsed_response[:errors]
|
||||||
render :edit
|
render file: 'registrar/bulk_change/new', locals: { active_tab: :nameserver }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
58
app/controllers/registrar/tech_contacts_controller.rb
Normal file
58
app/controllers/registrar/tech_contacts_controller.rb
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
class Registrar
|
||||||
|
class TechContactsController < BulkChangeController
|
||||||
|
def update
|
||||||
|
authorize! :manage, :repp
|
||||||
|
|
||||||
|
uri = URI.parse("#{ENV['repp_url']}domains/contacts")
|
||||||
|
|
||||||
|
request = Net::HTTP::Patch.new(uri)
|
||||||
|
request.set_form_data(predecessor: params[:predecessor], successor: params[:successor])
|
||||||
|
request.basic_auth(current_user.username, current_user.password)
|
||||||
|
|
||||||
|
if Rails.env.test?
|
||||||
|
response = Net::HTTP.start(uri.hostname, uri.port,
|
||||||
|
use_ssl: (uri.scheme == 'https'),
|
||||||
|
verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http|
|
||||||
|
http.request(request)
|
||||||
|
end
|
||||||
|
elsif Rails.env.development?
|
||||||
|
client_cert = File.read(ENV['cert_path'])
|
||||||
|
client_key = File.read(ENV['key_path'])
|
||||||
|
response = Net::HTTP.start(uri.hostname, uri.port,
|
||||||
|
use_ssl: (uri.scheme == 'https'),
|
||||||
|
verify_mode: OpenSSL::SSL::VERIFY_NONE,
|
||||||
|
cert: OpenSSL::X509::Certificate.new(client_cert),
|
||||||
|
key: OpenSSL::PKey::RSA.new(client_key)) do |http|
|
||||||
|
http.request(request)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
client_cert = File.read(ENV['cert_path'])
|
||||||
|
client_key = File.read(ENV['key_path'])
|
||||||
|
response = Net::HTTP.start(uri.hostname, uri.port,
|
||||||
|
use_ssl: (uri.scheme == 'https'),
|
||||||
|
cert: OpenSSL::X509::Certificate.new(client_cert),
|
||||||
|
key: OpenSSL::PKey::RSA.new(client_key)) do |http|
|
||||||
|
http.request(request)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
parsed_response = JSON.parse(response.body, symbolize_names: true)
|
||||||
|
|
||||||
|
if response.code == '200'
|
||||||
|
notices = [t('.replaced')]
|
||||||
|
|
||||||
|
notices << "#{t('.affected_domains')}: #{parsed_response[:affected_domains].join(', ')}"
|
||||||
|
|
||||||
|
if parsed_response[:skipped_domains]
|
||||||
|
notices << "#{t('.skipped_domains')}: #{parsed_response[:skipped_domains].join(', ')}"
|
||||||
|
end
|
||||||
|
|
||||||
|
flash[:notice] = notices
|
||||||
|
redirect_to registrar_domains_url
|
||||||
|
else
|
||||||
|
@error = parsed_response[:error]
|
||||||
|
render file: 'registrar/bulk_change/new', locals: { active_tab: :technical_contact }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,2 +1,23 @@
|
||||||
class TechDomainContact < DomainContact
|
class TechDomainContact < DomainContact
|
||||||
|
# Audit log is needed, therefore no raw SQL
|
||||||
|
def self.replace(predecessor, successor)
|
||||||
|
affected_domains = []
|
||||||
|
skipped_domains = []
|
||||||
|
tech_contacts = where(contact: predecessor)
|
||||||
|
|
||||||
|
transaction do
|
||||||
|
tech_contacts.each do |tech_contact|
|
||||||
|
if tech_contact.domain.discarded?
|
||||||
|
skipped_domains << tech_contact.domain.name
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
tech_contact.contact = successor
|
||||||
|
tech_contact.save!
|
||||||
|
affected_domains << tech_contact.domain.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return affected_domains.sort, skipped_domains.sort
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
<% if flash[:notice] %>
|
<% if flash[:notice] %>
|
||||||
<div class="alert alert-success alert-dismissible">
|
<div class="alert alert-success alert-dismissible">
|
||||||
<button class="close" data-dismiss="alert" type=button><span>×</span></button>
|
<button class="close" data-dismiss="alert" type=button><span>×</span></button>
|
||||||
<p><%= flash[:notice] %></p>
|
<% if flash[:notice].respond_to?(:join) %>
|
||||||
|
<p><%= flash[:notice].join('<br>').html_safe %></p>
|
||||||
|
<% else %>
|
||||||
|
<p><%= flash[:notice] %></p>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<%= render 'shared/flash' %>
|
<%= render 'flash_messages' %>
|
||||||
<% if depp_controller? %>
|
<% if depp_controller? %>
|
||||||
<%= render 'registrar/shared/epp_results' %>
|
<%= render 'registrar/shared/epp_results' %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
<%= form_tag registrar_update_registrar_nameserver_path, method: :put, class: 'form-horizontal' do %>
|
<%= form_tag registrar_nameservers_path, method: :patch, class: 'form-horizontal' do %>
|
||||||
|
<%= render 'registrar/domain_transfers/form/api_errors' %>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-md-2 control-label">
|
<div class="col-md-2 control-label">
|
||||||
<%= label_tag :old_hostname %>
|
<%= label_tag :old_hostname %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-5">
|
<div class="col-md-5">
|
||||||
<%= text_field_tag :old_hostname, params[:old_hostname], autofocus: true,
|
<%= text_field_tag :old_hostname, params[:old_hostname], required: true,
|
||||||
required: true,
|
|
||||||
class: 'form-control' %>
|
class: 'form-control' %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
48
app/views/registrar/bulk_change/_tech_contact_form.html.erb
Normal file
48
app/views/registrar/bulk_change/_tech_contact_form.html.erb
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<%= form_tag registrar_tech_contacts_path, method: :patch, class: 'form-horizontal' do %>
|
||||||
|
<% if @error %>
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<%= @error[:message] %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-2 control-label">
|
||||||
|
<%= label_tag :predecessor %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-5">
|
||||||
|
<%= text_field_tag :predecessor, params[:predecessor],
|
||||||
|
list: :contacts,
|
||||||
|
required: true,
|
||||||
|
autofocus: true,
|
||||||
|
class: 'form-control' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-2 control-label">
|
||||||
|
<%= label_tag :successor %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-5">
|
||||||
|
<%= text_field_tag :successor, params[:successor],
|
||||||
|
list: :contacts,
|
||||||
|
required: true,
|
||||||
|
class: 'form-control' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-5 col-md-offset-2 text-right">
|
||||||
|
<button class="btn btn-warning">
|
||||||
|
<%= t '.submit_btn' %>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<datalist id="contacts">
|
||||||
|
<% available_contacts.each do |data| %>
|
||||||
|
<option value="<%= data.second %>"><%= data.first %></option>
|
||||||
|
<% end %>
|
||||||
|
</datalist>
|
32
app/views/registrar/bulk_change/new.html.erb
Normal file
32
app/views/registrar/bulk_change/new.html.erb
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><%= link_to t('registrar.domains.index.header'), registrar_domains_path %></li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div class="page-header">
|
||||||
|
<h1><%= t '.header' %></h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-10">
|
||||||
|
<ul class="nav nav-tabs">
|
||||||
|
<li class="<%= 'active' if active_tab == :technical_contact %>">
|
||||||
|
<a href="#technical_contact" data-toggle="tab"><%= t '.technical_contact' %></a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="<%= 'active' if active_tab == :nameserver %>">
|
||||||
|
<a href="#nameserver" data-toggle="tab"><%= t '.nameserver' %></a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="tab-content">
|
||||||
|
<div class="tab-pane<%= ' active' if active_tab == :technical_contact %>"
|
||||||
|
id="technical_contact">
|
||||||
|
<%= render 'tech_contact_form', available_contacts: available_contacts %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-pane<%= ' active' if active_tab == :nameserver %>" id="nameserver">
|
||||||
|
<%= render 'nameserver_form' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,13 +1,13 @@
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-7">
|
<div class="col-sm-5">
|
||||||
<h1><%= t '.header' %></h1>
|
<h1><%= t '.header' %></h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-sm-5 text-right">
|
<div class="col-sm-7 text-right">
|
||||||
<%= link_to t('.new_btn'), new_registrar_domain_path, class: 'btn btn-primary' %>
|
<%= link_to t('.new_btn'), new_registrar_domain_path, class: 'btn btn-primary' %>
|
||||||
<%= link_to t('.transfer_btn'), new_registrar_domain_transfer_path, class: 'btn btn-default' %>
|
<%= link_to t('.transfer_btn'), new_registrar_domain_transfer_path, class: 'btn btn-default' %>
|
||||||
<%= link_to t('.replace_nameserver_btn'), registrar_edit_registrar_nameserver_path,
|
<%= link_to t('.bulk_change_btn'), new_registrar_bulk_change_path,
|
||||||
class: 'btn btn-default' %>
|
class: 'btn btn-default' %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -24,22 +24,22 @@
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover table-bordered table-condensed">
|
<table class="table table-hover table-bordered table-condensed">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="col-xs-2">
|
<th class="col-xs-2">
|
||||||
<%= sort_link(@q, 'name') %>
|
<%= sort_link(@q, 'name') %>
|
||||||
</th>
|
</th>
|
||||||
<th class="col-xs-2">
|
<th class="col-xs-2">
|
||||||
<%= sort_link @q, 'registrant_name', Registrant.model_name.human %>
|
<%= sort_link @q, 'registrant_name', Registrant.model_name.human %>
|
||||||
</th>
|
</th>
|
||||||
<th class="col-xs-2">
|
<th class="col-xs-2">
|
||||||
<%= sort_link @q, 'valid_to', Domain.human_attribute_name(:expire_time) %>
|
<%= sort_link @q, 'valid_to', Domain.human_attribute_name(:expire_time) %>
|
||||||
</th>
|
</th>
|
||||||
<th class="col-xs-2"></th>
|
<th class="col-xs-2"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
<%= render @domains %>
|
<%= render @domains %>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
<ol class="breadcrumb">
|
|
||||||
<li><%= link_to t('registrar.domains.index.header'), registrar_domains_path %></li>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<div class="page-header">
|
|
||||||
<h1><%= t '.header' %></h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<%= render 'registrar/domain_transfers/form/api_errors' %>
|
|
||||||
|
|
||||||
<%= render 'form' %>
|
|
14
config/locales/registrar/bulk_change.en.yml
Normal file
14
config/locales/registrar/bulk_change.en.yml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
en:
|
||||||
|
registrar:
|
||||||
|
bulk_change:
|
||||||
|
new:
|
||||||
|
header: Bulk change
|
||||||
|
technical_contact: Technical contact
|
||||||
|
nameserver: Nameserver
|
||||||
|
|
||||||
|
tech_contact_form:
|
||||||
|
submit_btn: Replace technical contacts
|
||||||
|
|
||||||
|
nameserver_form:
|
||||||
|
ip_hint: One IP per line
|
||||||
|
replace_btn: Replace nameserver
|
|
@ -5,7 +5,7 @@ en:
|
||||||
header: Domains
|
header: Domains
|
||||||
new_btn: New domain
|
new_btn: New domain
|
||||||
transfer_btn: Transfer
|
transfer_btn: Transfer
|
||||||
replace_nameserver_btn: Replace nameserver
|
bulk_change_btn: Bulk change
|
||||||
csv:
|
csv:
|
||||||
domain_name: Domain
|
domain_name: Domain
|
||||||
transfer_code: Transfer code
|
transfer_code: Transfer code
|
||||||
|
|
5
config/locales/registrar/nameservers.en.yml
Normal file
5
config/locales/registrar/nameservers.en.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
en:
|
||||||
|
registrar:
|
||||||
|
nameservers:
|
||||||
|
update:
|
||||||
|
replaced: Nameserver have been successfully replaced
|
|
@ -1,13 +0,0 @@
|
||||||
en:
|
|
||||||
registrar:
|
|
||||||
registrar_nameservers:
|
|
||||||
edit:
|
|
||||||
header: Replace nameserver
|
|
||||||
replace_btn: Replace
|
|
||||||
|
|
||||||
form:
|
|
||||||
ip_hint: One IP per line
|
|
||||||
replace_btn: Replace nameserver
|
|
||||||
|
|
||||||
update:
|
|
||||||
replaced: Nameserver have been successfully replaced
|
|
7
config/locales/registrar/tech_contacts.en.yml
Normal file
7
config/locales/registrar/tech_contacts.en.yml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
en:
|
||||||
|
registrar:
|
||||||
|
tech_contacts:
|
||||||
|
update:
|
||||||
|
replaced: Technical contacts have been successfully replaced.
|
||||||
|
affected_domains: Affected domains
|
||||||
|
skipped_domains: Skipped domains
|
|
@ -62,9 +62,9 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
resources :domain_transfers, only: %i[new create]
|
resources :domain_transfers, only: %i[new create]
|
||||||
get 'registrar/nameservers', to: 'registrar_nameservers#edit', as: :edit_registrar_nameserver
|
resource :bulk_change, controller: :bulk_change, only: :new
|
||||||
put 'registrar/nameservers', to: 'registrar_nameservers#update', as: :update_registrar_nameserver
|
resource :tech_contacts, only: :update
|
||||||
|
resource :nameservers, only: :update
|
||||||
resources :contacts, constraints: {:id => /[^\/]+(?=#{ ActionController::Renderers::RENDERERS.map{|e| "\\.#{e}\\z"}.join("|") })|[^\/]+/} do
|
resources :contacts, constraints: {:id => /[^\/]+(?=#{ ActionController::Renderers::RENDERERS.map{|e| "\\.#{e}\\z"}.join("|") })|[^\/]+/} do
|
||||||
member do
|
member do
|
||||||
get 'delete'
|
get 'delete'
|
||||||
|
|
19
doc/repp/v1/domain_contacts.md
Normal file
19
doc/repp/v1/domain_contacts.md
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# Domain contacts
|
||||||
|
|
||||||
|
## PATCH https://repp.internet.ee/v1/domains/contacts
|
||||||
|
Replaces all domain contacts of the current registrar.
|
||||||
|
|
||||||
|
### Example request
|
||||||
|
```
|
||||||
|
$ curl https://repp.internet.ee/v1/domains/contacts \
|
||||||
|
-X PATCH \
|
||||||
|
-u username:password \
|
||||||
|
-d predecessor=foo \
|
||||||
|
-d successor=bar
|
||||||
|
```
|
||||||
|
### Example response
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"affected_domains": ["example.com", "example.org"]
|
||||||
|
}
|
||||||
|
```
|
15
test/fixtures/domain_contacts.yml
vendored
15
test/fixtures/domain_contacts.yml
vendored
|
@ -8,11 +8,26 @@ shop_william:
|
||||||
contact: william
|
contact: william
|
||||||
type: TechDomainContact
|
type: TechDomainContact
|
||||||
|
|
||||||
|
shop_acme_ltd:
|
||||||
|
domain: shop
|
||||||
|
contact: acme_ltd
|
||||||
|
type: TechDomainContact
|
||||||
|
|
||||||
airport_john:
|
airport_john:
|
||||||
domain: airport
|
domain: airport
|
||||||
contact: john
|
contact: john
|
||||||
type: AdminDomainContact
|
type: AdminDomainContact
|
||||||
|
|
||||||
|
airport_william_admin:
|
||||||
|
domain: airport
|
||||||
|
contact: william
|
||||||
|
type: AdminDomainContact
|
||||||
|
|
||||||
|
airport_william_tech:
|
||||||
|
domain: airport
|
||||||
|
contact: william
|
||||||
|
type: TechDomainContact
|
||||||
|
|
||||||
library_john:
|
library_john:
|
||||||
domain: library
|
domain: library
|
||||||
contact: john
|
contact: john
|
||||||
|
|
4
test/fixtures/nameservers.yml
vendored
4
test/fixtures/nameservers.yml
vendored
|
@ -18,6 +18,10 @@ airport_ns1:
|
||||||
hostname: ns1.bestnames.test
|
hostname: ns1.bestnames.test
|
||||||
domain: airport
|
domain: airport
|
||||||
|
|
||||||
|
airport_ns2:
|
||||||
|
hostname: ns2.bestnames.test
|
||||||
|
domain: airport
|
||||||
|
|
||||||
metro_ns1:
|
metro_ns1:
|
||||||
hostname: ns1.bestnames.test
|
hostname: ns1.bestnames.test
|
||||||
domain: metro
|
domain: metro
|
||||||
|
|
103
test/integration/api/domain_contacts_test.rb
Normal file
103
test/integration/api/domain_contacts_test.rb
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class APIDomainContactsTest < ActionDispatch::IntegrationTest
|
||||||
|
def test_replace_all_tech_contacts_of_the_current_registrar
|
||||||
|
patch '/repp/v1/domains/contacts', { predecessor: 'william-001', successor: 'john-001' },
|
||||||
|
{ 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
|
assert_nil domains(:shop).tech_contacts.find_by(code: 'william-001')
|
||||||
|
assert domains(:shop).tech_contacts.find_by(code: 'john-001')
|
||||||
|
assert domains(:airport).tech_contacts.find_by(code: 'john-001')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_skip_discarded_domains
|
||||||
|
domains(:airport).update!(statuses: [DomainStatus::DELETE_CANDIDATE])
|
||||||
|
|
||||||
|
patch '/repp/v1/domains/contacts', { predecessor: 'william-001', successor: 'john-001' },
|
||||||
|
{ 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
|
assert domains(:airport).tech_contacts.find_by(code: 'william-001')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_return_affected_domains_in_alphabetical_order
|
||||||
|
patch '/repp/v1/domains/contacts', { predecessor: 'william-001', successor: 'john-001' },
|
||||||
|
{ 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
|
assert_response :ok
|
||||||
|
assert_equal ({ affected_domains: %w[airport.test shop.test],
|
||||||
|
skipped_domains: [] }),
|
||||||
|
JSON.parse(response.body, symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_return_skipped_domains_in_alphabetical_order
|
||||||
|
domains(:shop).update!(statuses: [DomainStatus::DELETE_CANDIDATE])
|
||||||
|
domains(:airport).update!(statuses: [DomainStatus::DELETE_CANDIDATE])
|
||||||
|
|
||||||
|
patch '/repp/v1/domains/contacts', { predecessor: 'william-001', successor: 'john-001' },
|
||||||
|
{ 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
|
assert_response :ok
|
||||||
|
assert_equal %w[airport.test shop.test], JSON.parse(response.body,
|
||||||
|
symbolize_names: true)[:skipped_domains]
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_keep_other_tech_contacts_intact
|
||||||
|
patch '/repp/v1/domains/contacts', { predecessor: 'william-001', successor: 'john-001' },
|
||||||
|
{ 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
|
assert domains(:shop).tech_contacts.find_by(code: 'acme-ltd-001')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_keep_admin_contacts_intact
|
||||||
|
patch '/repp/v1/domains/contacts', { predecessor: 'william-001', successor: 'john-001' },
|
||||||
|
{ 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
|
assert domains(:airport).admin_contacts.find_by(code: 'william-001')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_restrict_contacts_to_the_current_registrar
|
||||||
|
patch '/repp/v1/domains/contacts', { predecessor: 'jack-001', successor: 'william-002' },
|
||||||
|
{ 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
|
assert_response :bad_request
|
||||||
|
assert_equal ({ error: { type: 'invalid_request_error',
|
||||||
|
param: 'predecessor',
|
||||||
|
message: 'No such contact: jack-001' } }),
|
||||||
|
JSON.parse(response.body, symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_non_existent_predecessor
|
||||||
|
patch '/repp/v1/domains/contacts', { predecessor: 'non-existent', successor: 'john-001' },
|
||||||
|
{ 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
assert_response :bad_request
|
||||||
|
assert_equal ({ error: { type: 'invalid_request_error',
|
||||||
|
param: 'predecessor',
|
||||||
|
message: 'No such contact: non-existent' } }),
|
||||||
|
JSON.parse(response.body, symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_non_existent_successor
|
||||||
|
patch '/repp/v1/domains/contacts', { predecessor: 'william-001', successor: 'non-existent' },
|
||||||
|
{ 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
assert_response :bad_request
|
||||||
|
assert_equal ({ error: { type: 'invalid_request_error',
|
||||||
|
param: 'successor',
|
||||||
|
message: 'No such contact: non-existent' } }),
|
||||||
|
JSON.parse(response.body, symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_disallow_self_replacement
|
||||||
|
patch '/repp/v1/domains/contacts', { predecessor: 'william-001', successor: 'william-001' },
|
||||||
|
{ 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
assert_response :bad_request
|
||||||
|
assert_equal ({ error: { type: 'invalid_request_error',
|
||||||
|
message: 'Successor contact must be different from predecessor' } }),
|
||||||
|
JSON.parse(response.body, symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def http_auth_key
|
||||||
|
ActionController::HttpAuthentication::Basic.encode_credentials('test_bestnames', 'testtest')
|
||||||
|
end
|
||||||
|
end
|
|
@ -53,7 +53,7 @@ class APIDomainTransfersTest < ActionDispatch::IntegrationTest
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_duplicates_registrant_admin_and_tech_contacts
|
def test_duplicates_registrant_admin_and_tech_contacts
|
||||||
assert_difference -> { @new_registrar.contacts.size }, 2 do
|
assert_difference -> { @new_registrar.contacts.size }, 3 do
|
||||||
post '/repp/v1/domain_transfers', request_params, { 'HTTP_AUTHORIZATION' => http_auth_key }
|
post '/repp/v1/domain_transfers', request_params, { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -49,7 +49,7 @@ class EppDomainTransferRequestTest < ActionDispatch::IntegrationTest
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_duplicates_registrant_admin_and_tech_contacts
|
def test_duplicates_registrant_admin_and_tech_contacts
|
||||||
assert_difference -> { @new_registrar.contacts.size }, 2 do
|
assert_difference -> { @new_registrar.contacts.size }, 3 do
|
||||||
post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
|
post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class RegistrarNameserverReplacementTest < ActionDispatch::IntegrationTest
|
class RegistrarAreaNameserverBulkChangeTest < ActionDispatch::IntegrationTest
|
||||||
def setup
|
setup do
|
||||||
WebMock.reset!
|
|
||||||
login_as users(:api_goodnames)
|
login_as users(:api_goodnames)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -21,7 +20,8 @@ class RegistrarNameserverReplacementTest < ActionDispatch::IntegrationTest
|
||||||
}] }.to_json, status: 200)
|
}] }.to_json, status: 200)
|
||||||
|
|
||||||
visit registrar_domains_url
|
visit registrar_domains_url
|
||||||
click_link 'Replace nameserver'
|
click_link 'Bulk change'
|
||||||
|
click_link 'Nameserver'
|
||||||
|
|
||||||
fill_in 'Old hostname', with: 'ns1.bestnames.test'
|
fill_in 'Old hostname', with: 'ns1.bestnames.test'
|
||||||
fill_in 'New hostname', with: 'new-ns.bestnames.test'
|
fill_in 'New hostname', with: 'new-ns.bestnames.test'
|
||||||
|
@ -40,7 +40,8 @@ class RegistrarNameserverReplacementTest < ActionDispatch::IntegrationTest
|
||||||
headers: { 'Content-type' => 'application/json' })
|
headers: { 'Content-type' => 'application/json' })
|
||||||
|
|
||||||
visit registrar_domains_url
|
visit registrar_domains_url
|
||||||
click_link 'Replace nameserver'
|
click_link 'Bulk change'
|
||||||
|
click_link 'Nameserver'
|
||||||
|
|
||||||
fill_in 'Old hostname', with: 'old hostname'
|
fill_in 'Old hostname', with: 'old hostname'
|
||||||
fill_in 'New hostname', with: 'new hostname'
|
fill_in 'New hostname', with: 'new hostname'
|
47
test/integration/registrar/bulk_change/tech_contact_test.rb
Normal file
47
test/integration/registrar/bulk_change/tech_contact_test.rb
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class RegistrarAreaTechContactBulkChangeTest < ActionDispatch::IntegrationTest
|
||||||
|
setup do
|
||||||
|
login_as users(:api_bestnames)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_replace_domain_contacts_of_current_registrar
|
||||||
|
request_stub = stub_request(:patch, /domains\/contacts/)
|
||||||
|
.with(body: { predecessor: 'william-001', successor: 'john-001' },
|
||||||
|
basic_auth: ['test_bestnames', 'testtest'])
|
||||||
|
.to_return(body: { affected_domains: %w[foo.test bar.test],
|
||||||
|
skipped_domains: %w[baz.test qux.test] }.to_json,
|
||||||
|
status: 200)
|
||||||
|
|
||||||
|
visit registrar_domains_url
|
||||||
|
click_link 'Bulk change'
|
||||||
|
|
||||||
|
fill_in 'Predecessor', with: 'william-001'
|
||||||
|
fill_in 'Successor', with: 'john-001'
|
||||||
|
click_on 'Replace technical contacts'
|
||||||
|
|
||||||
|
assert_requested request_stub
|
||||||
|
assert_current_path registrar_domains_path
|
||||||
|
assert_text 'Technical contacts have been successfully replaced'
|
||||||
|
assert_text 'Affected domains: foo.test, bar.test'
|
||||||
|
assert_text 'Skipped domains: baz.test, qux.test'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_fails_gracefully
|
||||||
|
stub_request(:patch, /domains\/contacts/)
|
||||||
|
.to_return(status: 400,
|
||||||
|
body: { error: { message: 'epic fail' } }.to_json,
|
||||||
|
headers: { 'Content-type' => 'application/json' })
|
||||||
|
|
||||||
|
visit registrar_domains_url
|
||||||
|
click_link 'Bulk change'
|
||||||
|
|
||||||
|
fill_in 'Predecessor', with: 'william-001'
|
||||||
|
fill_in 'Successor', with: 'john-001'
|
||||||
|
click_on 'Replace technical contacts'
|
||||||
|
|
||||||
|
assert_text 'epic fail'
|
||||||
|
assert_field 'Predecessor', with: 'william-001'
|
||||||
|
assert_field 'Successor', with: 'john-001'
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,8 +1,7 @@
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class RegistrarDomainTransfersTest < ActionDispatch::IntegrationTest
|
class RegistrarDomainTransfersTest < ActionDispatch::IntegrationTest
|
||||||
def setup
|
setup do
|
||||||
WebMock.reset!
|
|
||||||
login_as users(:api_goodnames)
|
login_as users(:api_goodnames)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ class DomainTransferTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
body = 'Transfer of domain shop.test has been approved.' \
|
body = 'Transfer of domain shop.test has been approved.' \
|
||||||
' It was associated with registrant john-001' \
|
' It was associated with registrant john-001' \
|
||||||
' and contacts jane-001, william-001.'
|
' and contacts acme-ltd-001, jane-001, william-001.'
|
||||||
id = @domain_transfer.id
|
id = @domain_transfer.id
|
||||||
class_name = @domain_transfer.class.name
|
class_name = @domain_transfer.class.name
|
||||||
|
|
||||||
|
|
|
@ -50,9 +50,11 @@ class NameserverTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_hostnames
|
def test_hostnames
|
||||||
assert_equal %w[ns1.bestnames.test
|
assert_equal %w[
|
||||||
|
ns1.bestnames.test
|
||||||
ns2.bestnames.test
|
ns2.bestnames.test
|
||||||
ns1.bestnames.test
|
ns1.bestnames.test
|
||||||
|
ns2.bestnames.test
|
||||||
ns1.bestnames.test], Nameserver.hostnames
|
ns1.bestnames.test], Nameserver.hostnames
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue