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::DomainTransfersV1
|
||||
mount Repp::NameserversV1
|
||||
mount Repp::DomainContactsV1
|
||||
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 RegistrarNameserversController < DeppController
|
||||
def edit
|
||||
authorize! :manage, :repp
|
||||
end
|
||||
|
||||
class NameserversController < BulkChangeController
|
||||
def update
|
||||
authorize! :manage, :repp
|
||||
|
||||
|
@ -52,7 +48,7 @@ class Registrar
|
|||
redirect_to registrar_domains_url
|
||||
else
|
||||
@api_errors = parsed_response[:errors]
|
||||
render :edit
|
||||
render file: 'registrar/bulk_change/new', locals: { active_tab: :nameserver }
|
||||
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
|
||||
# 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
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
<% if flash[:notice] %>
|
||||
<div class="alert alert-success alert-dismissible">
|
||||
<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>
|
||||
<% end %>
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
</div>
|
||||
</nav>
|
||||
<div class="container">
|
||||
<%= render 'shared/flash' %>
|
||||
<%= render 'flash_messages' %>
|
||||
<% if depp_controller? %>
|
||||
<%= render 'registrar/shared/epp_results' %>
|
||||
<% 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="col-md-2 control-label">
|
||||
<%= label_tag :old_hostname %>
|
||||
</div>
|
||||
|
||||
<div class="col-md-5">
|
||||
<%= text_field_tag :old_hostname, params[:old_hostname], autofocus: true,
|
||||
required: true,
|
||||
<%= text_field_tag :old_hostname, params[:old_hostname], required: true,
|
||||
class: 'form-control' %>
|
||||
</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="row">
|
||||
<div class="col-sm-7">
|
||||
<div class="col-sm-5">
|
||||
<h1><%= t '.header' %></h1>
|
||||
</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('.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' %>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -24,22 +24,22 @@
|
|||
<div class="table-responsive">
|
||||
<table class="table table-hover table-bordered table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-xs-2">
|
||||
<%= sort_link(@q, 'name') %>
|
||||
</th>
|
||||
<th class="col-xs-2">
|
||||
<%= sort_link @q, 'registrant_name', Registrant.model_name.human %>
|
||||
</th>
|
||||
<th class="col-xs-2">
|
||||
<%= sort_link @q, 'valid_to', Domain.human_attribute_name(:expire_time) %>
|
||||
</th>
|
||||
<th class="col-xs-2"></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="col-xs-2">
|
||||
<%= sort_link(@q, 'name') %>
|
||||
</th>
|
||||
<th class="col-xs-2">
|
||||
<%= sort_link @q, 'registrant_name', Registrant.model_name.human %>
|
||||
</th>
|
||||
<th class="col-xs-2">
|
||||
<%= sort_link @q, 'valid_to', Domain.human_attribute_name(:expire_time) %>
|
||||
</th>
|
||||
<th class="col-xs-2"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<%= render @domains %>
|
||||
<%= render @domains %>
|
||||
</tbody>
|
||||
</table>
|
||||
</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
|
||||
new_btn: New domain
|
||||
transfer_btn: Transfer
|
||||
replace_nameserver_btn: Replace nameserver
|
||||
bulk_change_btn: Bulk change
|
||||
csv:
|
||||
domain_name: Domain
|
||||
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
|
||||
resources :domain_transfers, only: %i[new create]
|
||||
get 'registrar/nameservers', to: 'registrar_nameservers#edit', as: :edit_registrar_nameserver
|
||||
put 'registrar/nameservers', to: 'registrar_nameservers#update', as: :update_registrar_nameserver
|
||||
|
||||
resource :bulk_change, controller: :bulk_change, only: :new
|
||||
resource :tech_contacts, only: :update
|
||||
resource :nameservers, only: :update
|
||||
resources :contacts, constraints: {:id => /[^\/]+(?=#{ ActionController::Renderers::RENDERERS.map{|e| "\\.#{e}\\z"}.join("|") })|[^\/]+/} do
|
||||
member do
|
||||
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
|
||||
type: TechDomainContact
|
||||
|
||||
shop_acme_ltd:
|
||||
domain: shop
|
||||
contact: acme_ltd
|
||||
type: TechDomainContact
|
||||
|
||||
airport_john:
|
||||
domain: airport
|
||||
contact: john
|
||||
type: AdminDomainContact
|
||||
|
||||
airport_william_admin:
|
||||
domain: airport
|
||||
contact: william
|
||||
type: AdminDomainContact
|
||||
|
||||
airport_william_tech:
|
||||
domain: airport
|
||||
contact: william
|
||||
type: TechDomainContact
|
||||
|
||||
library_john:
|
||||
domain: library
|
||||
contact: john
|
||||
|
|
4
test/fixtures/nameservers.yml
vendored
4
test/fixtures/nameservers.yml
vendored
|
@ -18,6 +18,10 @@ airport_ns1:
|
|||
hostname: ns1.bestnames.test
|
||||
domain: airport
|
||||
|
||||
airport_ns2:
|
||||
hostname: ns2.bestnames.test
|
||||
domain: airport
|
||||
|
||||
metro_ns1:
|
||||
hostname: ns1.bestnames.test
|
||||
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
|
||||
|
||||
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 }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -49,7 +49,7 @@ class EppDomainTransferRequestTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
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' }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
require 'test_helper'
|
||||
|
||||
class RegistrarNameserverReplacementTest < ActionDispatch::IntegrationTest
|
||||
def setup
|
||||
WebMock.reset!
|
||||
class RegistrarAreaNameserverBulkChangeTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
login_as users(:api_goodnames)
|
||||
end
|
||||
|
||||
|
@ -21,7 +20,8 @@ class RegistrarNameserverReplacementTest < ActionDispatch::IntegrationTest
|
|||
}] }.to_json, status: 200)
|
||||
|
||||
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 'New hostname', with: 'new-ns.bestnames.test'
|
||||
|
@ -40,7 +40,8 @@ class RegistrarNameserverReplacementTest < ActionDispatch::IntegrationTest
|
|||
headers: { 'Content-type' => 'application/json' })
|
||||
|
||||
visit registrar_domains_url
|
||||
click_link 'Replace nameserver'
|
||||
click_link 'Bulk change'
|
||||
click_link 'Nameserver'
|
||||
|
||||
fill_in 'Old hostname', with: 'old 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'
|
||||
|
||||
class RegistrarDomainTransfersTest < ActionDispatch::IntegrationTest
|
||||
def setup
|
||||
WebMock.reset!
|
||||
setup do
|
||||
login_as users(:api_goodnames)
|
||||
end
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class DomainTransferTest < ActiveSupport::TestCase
|
|||
|
||||
body = 'Transfer of domain shop.test has been approved.' \
|
||||
' 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
|
||||
class_name = @domain_transfer.class.name
|
||||
|
||||
|
|
|
@ -50,9 +50,11 @@ class NameserverTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
def test_hostnames
|
||||
assert_equal %w[ns1.bestnames.test
|
||||
assert_equal %w[
|
||||
ns1.bestnames.test
|
||||
ns2.bestnames.test
|
||||
ns1.bestnames.test
|
||||
ns2.bestnames.test
|
||||
ns1.bestnames.test], Nameserver.hostnames
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue