diff --git a/app/api/repp/api.rb b/app/api/repp/api.rb index 9c12470a0..7858cd625 100644 --- a/app/api/repp/api.rb +++ b/app/api/repp/api.rb @@ -59,5 +59,6 @@ module Repp mount Repp::AccountV1 mount Repp::DomainTransfersV1 mount Repp::NameserversV1 + mount Repp::DomainContactsV1 end end diff --git a/app/api/repp/domain_contacts_v1.rb b/app/api/repp/domain_contacts_v1.rb new file mode 100644 index 000000000..2d2cc4dbb --- /dev/null +++ b/app/api/repp/domain_contacts_v1.rb @@ -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 diff --git a/app/controllers/registrar/bulk_change_controller.rb b/app/controllers/registrar/bulk_change_controller.rb new file mode 100644 index 000000000..562344a46 --- /dev/null +++ b/app/controllers/registrar/bulk_change_controller.rb @@ -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 diff --git a/app/controllers/registrar/registrar_nameservers_controller.rb b/app/controllers/registrar/nameservers_controller.rb similarity index 94% rename from app/controllers/registrar/registrar_nameservers_controller.rb rename to app/controllers/registrar/nameservers_controller.rb index 1af3cde64..b6f7af829 100644 --- a/app/controllers/registrar/registrar_nameservers_controller.rb +++ b/app/controllers/registrar/nameservers_controller.rb @@ -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 diff --git a/app/controllers/registrar/tech_contacts_controller.rb b/app/controllers/registrar/tech_contacts_controller.rb new file mode 100644 index 000000000..fccb10f78 --- /dev/null +++ b/app/controllers/registrar/tech_contacts_controller.rb @@ -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 diff --git a/app/models/tech_domain_contact.rb b/app/models/tech_domain_contact.rb index 68ae35dde..55cc45aed 100644 --- a/app/models/tech_domain_contact.rb +++ b/app/models/tech_domain_contact.rb @@ -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 diff --git a/app/views/admin/base/_flash_messages.html.erb b/app/views/application/_flash_messages.html.erb similarity index 77% rename from app/views/admin/base/_flash_messages.html.erb rename to app/views/application/_flash_messages.html.erb index 4a10df304..9b31f0d3f 100644 --- a/app/views/admin/base/_flash_messages.html.erb +++ b/app/views/application/_flash_messages.html.erb @@ -1,7 +1,11 @@ <% if flash[:notice] %>
<%= flash[:notice] %>
+ <% if flash[:notice].respond_to?(:join) %> +<%= flash[:notice].join('
').html_safe %>
<%= flash[:notice] %>
+ <% end %>- <%= sort_link(@q, 'name') %> - | -- <%= sort_link @q, 'registrant_name', Registrant.model_name.human %> - | -- <%= sort_link @q, 'valid_to', Domain.human_attribute_name(:expire_time) %> - | -- |
---|---|---|---|
+ <%= sort_link(@q, 'name') %> + | ++ <%= sort_link @q, 'registrant_name', Registrant.model_name.human %> + | ++ <%= sort_link @q, 'valid_to', Domain.human_attribute_name(:expire_time) %> + | ++ |