mirror of
https://github.com/internetee/registry.git
synced 2025-06-06 04:37:30 +02:00
Merge remote-tracking branch 'origin/add-registrant-api-token-log' into add-role-filter-to-registrant-api
This commit is contained in:
commit
f60bf4013c
60 changed files with 1153 additions and 178 deletions
|
@ -16,8 +16,10 @@ plugins:
|
|||
enabled: true
|
||||
config:
|
||||
languages:
|
||||
- ruby
|
||||
- javascript
|
||||
ruby:
|
||||
mass_threshold: 100
|
||||
javascript:
|
||||
mass_threshold: 100
|
||||
eslint:
|
||||
enabled: true
|
||||
channel: eslint-5
|
||||
|
|
23
CHANGELOG.md
23
CHANGELOG.md
|
@ -1,3 +1,26 @@
|
|||
22.02.2021
|
||||
* serverDeleteProhibited prohibts delete action [#1849](https://github.com/internetee/registry/issues/1849)
|
||||
|
||||
19.02.2021
|
||||
* Update prohibited staatus is kept after renew [#1843](https://github.com/internetee/registry/issues/1843)
|
||||
* Fixed clientHold and serverManualInzone status conflict issue [#1845](https://github.com/internetee/registry/issues/1845)
|
||||
* Replacing registrant object with another that has the same ident data set does not require registrant verification [#1852](https://github.com/internetee/registry/issues/1852)
|
||||
|
||||
11.02.2021
|
||||
* Poll messages on locking and unlocking a domain [#1828](https://github.com/internetee/registry/issues/1828)
|
||||
* Registrar's prefix is now checked and added to contact id for info and check requests [#1832](https://github.com/internetee/registry/issues/1832)
|
||||
|
||||
10.02.2021
|
||||
* Admin contact bulk change option for registrars [#1764](https://github.com/internetee/registry/issues/1764)
|
||||
* Option to remove email addresses from AWS SES Supression list [#1839](https://github.com/internetee/registry/issues/1839)
|
||||
* Added separate key for bounce API [#1842](https://github.com/internetee/registry/pull/1842)
|
||||
|
||||
09.02.2021
|
||||
* Added new endpoint for WHOIS contact requests [#1794](https://github.com/internetee/registry/pull/1794)
|
||||
|
||||
05.02.2021
|
||||
* Fixed IPv4 empty string issue in case of IPv6 only entries for IP whitelist [#1833](https://github.com/internetee/registry/issues/1833)
|
||||
|
||||
02.02.2021
|
||||
* Fixed updateProhibited status not affecting bulk tech contact change operation [#1820](https://github.com/internetee/registry/pull/1820)
|
||||
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -92,3 +92,5 @@ group :test do
|
|||
gem 'webdrivers'
|
||||
gem 'webmock'
|
||||
end
|
||||
|
||||
gem 'aws-sdk-sesv2', '~> 1.16'
|
||||
|
|
14
Gemfile.lock
14
Gemfile.lock
|
@ -148,6 +148,18 @@ GEM
|
|||
attr_required (1.0.1)
|
||||
autoprefixer-rails (10.0.0.2)
|
||||
execjs
|
||||
aws-eventstream (1.1.0)
|
||||
aws-partitions (1.424.0)
|
||||
aws-sdk-core (3.112.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
aws-partitions (~> 1, >= 1.239.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
jmespath (~> 1.0)
|
||||
aws-sdk-sesv2 (1.16.0)
|
||||
aws-sdk-core (~> 3, >= 3.112.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sigv4 (1.2.2)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
bcrypt (3.1.16)
|
||||
bindata (2.4.8)
|
||||
bootsnap (1.4.8)
|
||||
|
@ -226,6 +238,7 @@ GEM
|
|||
i18n_data (0.10.0)
|
||||
isikukood (0.1.2)
|
||||
iso8601 (0.12.1)
|
||||
jmespath (1.4.0)
|
||||
jquery-rails (4.4.0)
|
||||
rails-dom-testing (>= 1, < 3)
|
||||
railties (>= 4.2.0)
|
||||
|
@ -484,6 +497,7 @@ DEPENDENCIES
|
|||
active_interaction (~> 3.8)
|
||||
activerecord-import
|
||||
airbrake
|
||||
aws-sdk-sesv2 (~> 1.16)
|
||||
bootsnap (>= 1.1.0)
|
||||
bootstrap-sass (~> 3.4)
|
||||
cancancan
|
||||
|
|
|
@ -11,7 +11,7 @@ module Api
|
|||
end
|
||||
|
||||
def authenticate_shared_key
|
||||
api_key = "Basic #{ENV['api_shared_key']}"
|
||||
api_key = "Basic #{ENV['rwhois_internal_api_shared_key']}"
|
||||
head(:unauthorized) unless api_key == request.authorization
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Api
|
||||
module V1
|
||||
class BouncesController < BaseController
|
||||
before_action :authenticate_shared_key
|
||||
before_action :validate_shared_key_integrity
|
||||
|
||||
# POST api/v1/bounces/
|
||||
def create
|
||||
|
@ -20,6 +20,13 @@ module Api
|
|||
|
||||
params.require(:data)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_shared_key_integrity
|
||||
api_key = "Basic #{ENV['rwhois_bounces_api_shared_key']}"
|
||||
head(:unauthorized) unless api_key == request.authorization
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
37
app/controllers/api/v1/contact_requests_controller.rb
Normal file
37
app/controllers/api/v1/contact_requests_controller.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
module Api
|
||||
module V1
|
||||
class ContactRequestsController < BaseController
|
||||
before_action :authenticate_shared_key
|
||||
|
||||
# POST api/v1/contact_requests/
|
||||
def create
|
||||
return head(:bad_request) if contact_request_params[:email].blank?
|
||||
|
||||
contact_request = ContactRequest.save_record(contact_request_params)
|
||||
render json: contact_request, status: :created
|
||||
rescue StandardError
|
||||
head(:bad_request)
|
||||
end
|
||||
|
||||
def update
|
||||
return head(:bad_request) if params[:id].blank?
|
||||
|
||||
process_id(params[:id])
|
||||
end
|
||||
|
||||
def process_id(id)
|
||||
record = ContactRequest.find_by(id: id)
|
||||
return :not_found unless record
|
||||
|
||||
record.update_status(contact_request_params)
|
||||
render json: record, status: :ok
|
||||
rescue StandardError
|
||||
head :bad_request
|
||||
end
|
||||
|
||||
def contact_request_params
|
||||
params.require(:contact_request).permit(:email, :whois_record_id, :name, :status, :ip)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -19,6 +19,8 @@ module Api
|
|||
token = create_token(user)
|
||||
|
||||
if token
|
||||
ToStdout.msg("Bearer for #{eid_params[:first_name]} #{eid_params[:last_name]} " \
|
||||
"(#{eid_params[:ident]}) - '#{token[:access_token]}'")
|
||||
render json: token
|
||||
else
|
||||
render json: { errors: [{ base: ['Cannot create generate session token'] }] }
|
||||
|
|
|
@ -14,7 +14,7 @@ module Epp
|
|||
authorize! :check, Epp::Contact
|
||||
|
||||
ids = params[:parsed_frame].css('id').map(&:text)
|
||||
@results = Epp::Contact.check_availability(ids)
|
||||
@results = Epp::Contact.check_availability(ids, reg: current_user.registrar.code)
|
||||
render_epp_response '/epp/contacts/check'
|
||||
end
|
||||
|
||||
|
@ -93,7 +93,11 @@ module Epp
|
|||
|
||||
def find_contact
|
||||
code = params[:parsed_frame].css('id').text.strip.upcase
|
||||
@contact = Epp::Contact.find_by!(code: code)
|
||||
reg_code = current_user.registrar.code.upcase
|
||||
arr = [code, "#{reg_code}:#{code}", "CID:#{code}", "CID:#{reg_code}:#{code}"]
|
||||
|
||||
contact = arr.find { |c| Epp::Contact.find_by(code: c).present? }
|
||||
@contact = Epp::Contact.find_by!(code: contact || code)
|
||||
end
|
||||
|
||||
#
|
||||
|
|
18
app/controllers/registrar/admin_contacts_controller.rb
Normal file
18
app/controllers/registrar/admin_contacts_controller.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
class Registrar
|
||||
class AdminContactsController < BulkChangeController
|
||||
BASE_URL = URI.parse("#{ENV['repp_url']}domains/admin_contacts").freeze
|
||||
ACTIVE_TAB = :admin_contact
|
||||
|
||||
def update
|
||||
authorize! :manage, :repp
|
||||
uri = BASE_URL
|
||||
request = form_request(uri)
|
||||
response = do_request(request, uri)
|
||||
start_notice = t('.replaced')
|
||||
|
||||
process_response(response: response,
|
||||
start_notice: start_notice,
|
||||
active_tab: ACTIVE_TAB)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -26,6 +26,84 @@ class Registrar
|
|||
|
||||
private
|
||||
|
||||
def form_request(uri)
|
||||
request = Net::HTTP::Patch.new(uri)
|
||||
request.set_form_data(current_contact_id: params[:current_contact_id],
|
||||
new_contact_id: params[:new_contact_id])
|
||||
request.basic_auth(current_registrar_user.username,
|
||||
current_registrar_user.plain_text_password)
|
||||
request
|
||||
end
|
||||
|
||||
def process_response(response:, start_notice: '', active_tab:)
|
||||
parsed_response = JSON.parse(response.body, symbolize_names: true)
|
||||
|
||||
if response.code == '200'
|
||||
notices = success_notices(parsed_response, start_notice)
|
||||
|
||||
flash[:notice] = notices.join(', ')
|
||||
redirect_to registrar_domains_url
|
||||
else
|
||||
@error = response.code == '404' ? 'Contact(s) not found' : parsed_response[:message]
|
||||
render file: 'registrar/bulk_change/new', locals: { active_tab: active_tab }
|
||||
end
|
||||
end
|
||||
|
||||
def success_notices(parsed_response, start_notice)
|
||||
notices = [start_notice]
|
||||
|
||||
notices << "#{t('.affected_domains')}: " \
|
||||
"#{parsed_response[:data][:affected_domains].join(', ')}"
|
||||
|
||||
if parsed_response[:data][:skipped_domains]
|
||||
notices << "#{t('.skipped_domains')}: " \
|
||||
"#{parsed_response[:data][:skipped_domains].join(', ')}"
|
||||
end
|
||||
notices
|
||||
end
|
||||
|
||||
def do_request(request, uri)
|
||||
response = if Rails.env.test?
|
||||
do_test_request(request, uri)
|
||||
elsif Rails.env.development?
|
||||
do_dev_request(request, uri)
|
||||
else
|
||||
do_live_request(request, uri)
|
||||
end
|
||||
response
|
||||
end
|
||||
|
||||
def do_live_request(request, uri)
|
||||
client_cert = File.read(ENV['cert_path'])
|
||||
client_key = File.read(ENV['key_path'])
|
||||
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
|
||||
|
||||
def do_dev_request(request, uri)
|
||||
client_cert = File.read(ENV['cert_path'])
|
||||
client_key = File.read(ENV['key_path'])
|
||||
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
|
||||
end
|
||||
|
||||
def do_test_request(request, uri)
|
||||
Net::HTTP.start(uri.hostname, uri.port,
|
||||
use_ssl: (uri.scheme == 'https'),
|
||||
verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http|
|
||||
http.request(request)
|
||||
end
|
||||
end
|
||||
|
||||
def ready_to_renew?
|
||||
domain_ids_for_bulk_renew.present? && params[:renew].present?
|
||||
end
|
||||
|
|
|
@ -25,32 +25,7 @@ class Registrar
|
|||
current_registrar_user.plain_text_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
|
||||
response = do_request(request, uri)
|
||||
|
||||
parsed_response = JSON.parse(response.body, symbolize_names: true)
|
||||
|
||||
|
|
|
@ -18,32 +18,7 @@ class Registrar
|
|||
request.basic_auth(current_registrar_user.username,
|
||||
current_registrar_user.plain_text_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
|
||||
response = do_request(request, uri)
|
||||
|
||||
parsed_response = JSON.parse(response.body, symbolize_names: true)
|
||||
|
||||
|
|
|
@ -1,62 +1,19 @@
|
|||
class Registrar
|
||||
class TechContactsController < BulkChangeController
|
||||
BASE_URL = URI.parse("#{ENV['repp_url']}domains/contacts").freeze
|
||||
ACTIVE_TAB = :technical_contact
|
||||
|
||||
def update
|
||||
authorize! :manage, :repp
|
||||
|
||||
uri = URI.parse("#{ENV['repp_url']}domains/contacts")
|
||||
uri = BASE_URL
|
||||
request = form_request(uri)
|
||||
response = do_request(request, uri)
|
||||
start_notice = t('.replaced')
|
||||
|
||||
request = Net::HTTP::Patch.new(uri)
|
||||
request.set_form_data(current_contact_id: params[:current_contact_id],
|
||||
new_contact_id: params[:new_contact_id])
|
||||
request.basic_auth(current_registrar_user.username,
|
||||
current_registrar_user.plain_text_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[:data][:affected_domains].join(', ')}"
|
||||
|
||||
if parsed_response[:data][:skipped_domains]
|
||||
notices << "#{t('.skipped_domains')}: " \
|
||||
"#{parsed_response[:data][:skipped_domains].join(', ')}"
|
||||
end
|
||||
|
||||
flash[:notice] = notices.join(', ')
|
||||
redirect_to registrar_domains_url
|
||||
else
|
||||
@error = response.code == '404' ? 'Contact(s) not found' : parsed_response[:message]
|
||||
render file: 'registrar/bulk_change/new', locals: { active_tab: :technical_contact }
|
||||
end
|
||||
process_response(response: response,
|
||||
start_notice: start_notice,
|
||||
active_tab: ACTIVE_TAB)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
21
app/controllers/repp/v1/domains/admin_contacts_controller.rb
Normal file
21
app/controllers/repp/v1/domains/admin_contacts_controller.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
module Repp
|
||||
module V1
|
||||
module Domains
|
||||
class AdminContactsController < BaseContactsController
|
||||
def update
|
||||
super
|
||||
|
||||
unless @new_contact.identical_to?(@current_contact)
|
||||
@epp_errors << { code: 2304, msg: 'Admin contacts must be identical' }
|
||||
end
|
||||
|
||||
return handle_errors if @epp_errors.any?
|
||||
|
||||
affected, skipped = AdminDomainContact.replace(@current_contact, @new_contact)
|
||||
@response = { affected_domains: affected, skipped_domains: skipped }
|
||||
render_success(data: @response)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
31
app/controllers/repp/v1/domains/base_contacts_controller.rb
Normal file
31
app/controllers/repp/v1/domains/base_contacts_controller.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
module Repp
|
||||
module V1
|
||||
module Domains
|
||||
class BaseContactsController < BaseController
|
||||
before_action :set_current_contact, only: [:update]
|
||||
before_action :set_new_contact, only: [:update]
|
||||
|
||||
def set_current_contact
|
||||
@current_contact = current_user.registrar.contacts
|
||||
.find_by!(code: contact_params[:current_contact_id])
|
||||
end
|
||||
|
||||
def set_new_contact
|
||||
@new_contact = current_user.registrar.contacts.find_by!(code: params[:new_contact_id])
|
||||
end
|
||||
|
||||
def update
|
||||
@epp_errors ||= []
|
||||
@epp_errors << { code: 2304, msg: 'New contact must be valid' } if @new_contact.invalid?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def contact_params
|
||||
params.require(%i[current_contact_id new_contact_id])
|
||||
params.permit(:current_contact_id, :new_contact_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,23 +1,9 @@
|
|||
module Repp
|
||||
module V1
|
||||
module Domains
|
||||
class ContactsController < BaseController
|
||||
before_action :set_current_contact, only: [:update]
|
||||
before_action :set_new_contact, only: [:update]
|
||||
|
||||
def set_current_contact
|
||||
@current_contact = current_user.registrar.contacts.find_by!(
|
||||
code: contact_params[:current_contact_id]
|
||||
)
|
||||
end
|
||||
|
||||
def set_new_contact
|
||||
@new_contact = current_user.registrar.contacts.find_by!(code: params[:new_contact_id])
|
||||
end
|
||||
|
||||
class ContactsController < BaseContactsController
|
||||
def update
|
||||
@epp_errors ||= []
|
||||
@epp_errors << { code: 2304, msg: 'New contact must be valid' } if @new_contact.invalid?
|
||||
super
|
||||
|
||||
if @new_contact == @current_contact
|
||||
@epp_errors << { code: 2304, msg: 'New contact must be different from current' }
|
||||
|
@ -29,13 +15,6 @@ module Repp
|
|||
@response = { affected_domains: affected, skipped_domains: skipped }
|
||||
render_success(data: @response)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def contact_params
|
||||
params.require(%i[current_contact_id new_contact_id])
|
||||
params.permit(:current_contact_id, :new_contact_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,6 +19,11 @@ module Actions
|
|||
return
|
||||
end
|
||||
|
||||
if contact.delete_prohibited?
|
||||
contact.errors.add(:statuses, :delete_prohibited)
|
||||
return
|
||||
end
|
||||
|
||||
commit
|
||||
end
|
||||
|
||||
|
|
|
@ -1,2 +1,26 @@
|
|||
class AdminDomainContact < DomainContact
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
def self.replace(current_contact, new_contact)
|
||||
affected_domains = []
|
||||
skipped_domains = []
|
||||
admin_contacts = where(contact: current_contact)
|
||||
|
||||
admin_contacts.each do |admin_contact|
|
||||
if admin_contact.domain.bulk_update_prohibited?
|
||||
skipped_domains << admin_contact.domain.name
|
||||
next
|
||||
end
|
||||
begin
|
||||
admin_contact.contact = new_contact
|
||||
admin_contact.save!
|
||||
affected_domains << admin_contact.domain.name
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
skipped_domains << admin_contact.domain.name
|
||||
end
|
||||
end
|
||||
[affected_domains.sort, skipped_domains.sort]
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class BouncedMailAddress < ApplicationRecord
|
||||
validates :email, :message_id, :bounce_type, :bounce_subtype, :action, :status, presence: true
|
||||
after_destroy :destroy_aws_suppression
|
||||
|
||||
def bounce_reason
|
||||
"#{action} (#{status} #{diagnostic})"
|
||||
|
@ -25,4 +26,20 @@ class BouncedMailAddress < ApplicationRecord
|
|||
diagnostic: bounced_record['diagnosticCode'],
|
||||
}
|
||||
end
|
||||
|
||||
def destroy_aws_suppression
|
||||
return unless BouncedMailAddress.ses_configured?
|
||||
|
||||
res = Aws::SESV2::Client.new.delete_suppressed_destination(email_address: email)
|
||||
res.successful?
|
||||
rescue Aws::SESV2::Errors::ServiceError => e
|
||||
logger.warn("Suppression not removed. #{e}")
|
||||
end
|
||||
|
||||
def self.ses_configured?
|
||||
ses ||= Aws::SESV2::Client.new
|
||||
ses.config.credentials.access_key_id.present?
|
||||
rescue Aws::Errors::MissingRegionError
|
||||
false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,6 +11,13 @@ module Concerns::Contact::Identical
|
|||
ident_country_code
|
||||
org_name
|
||||
]
|
||||
|
||||
IDENTICAL_ATTRIBUTES = %w[
|
||||
ident
|
||||
ident_type
|
||||
ident_country_code
|
||||
].freeze
|
||||
|
||||
private_constant :IDENTIFIABLE_ATTRIBUTES
|
||||
|
||||
def identical(registrar)
|
||||
|
@ -20,6 +27,12 @@ module Concerns::Contact::Identical
|
|||
.where.not(id: id).take
|
||||
end
|
||||
|
||||
def identical_to?(contact)
|
||||
IDENTICAL_ATTRIBUTES.all? do |attribute|
|
||||
attributes[attribute] == contact.attributes[attribute]
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def identifiable_hash
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
module Concerns::Domain::Deletable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
DELETE_STATUSES = [
|
||||
DomainStatus::PENDING_DELETE_CONFIRMATION,
|
||||
DomainStatus::PENDING_DELETE,
|
||||
DomainStatus::FORCE_DELETE,
|
||||
].freeze
|
||||
|
||||
private
|
||||
|
||||
def delete_later
|
||||
|
|
|
@ -11,6 +11,11 @@ module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength
|
|||
lambda {
|
||||
where("(force_delete_data->>'contact_notification_sent_date') is null")
|
||||
}
|
||||
|
||||
HOLD_STATUSES = [
|
||||
DomainStatus::SERVER_HOLD,
|
||||
DomainStatus::CLIENT_HOLD,
|
||||
].freeze
|
||||
end
|
||||
|
||||
class_methods do
|
||||
|
@ -19,6 +24,10 @@ module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength
|
|||
end
|
||||
end
|
||||
|
||||
def hold_status?
|
||||
HOLD_STATUSES.any? { |status| statuses.include? status }
|
||||
end
|
||||
|
||||
def notification_template(explicit: nil)
|
||||
reason = explicit&.downcase
|
||||
return reason if %w[invalid_email invalid_phone].include?(reason)
|
||||
|
|
|
@ -12,6 +12,7 @@ module Concerns
|
|||
statuses << DomainStatus::SERVER_DELETE_PROHIBITED
|
||||
statuses << DomainStatus::SERVER_TRANSFER_PROHIBITED
|
||||
self.locked_by_registrant_at = Time.zone.now
|
||||
alert_registrar_lock_changes!(lock: true)
|
||||
|
||||
save!
|
||||
end
|
||||
|
@ -42,10 +43,21 @@ module Concerns
|
|||
statuses.delete(DomainStatus::SERVER_DELETE_PROHIBITED)
|
||||
statuses.delete(DomainStatus::SERVER_TRANSFER_PROHIBITED)
|
||||
self.locked_by_registrant_at = nil
|
||||
alert_registrar_lock_changes!(lock: false)
|
||||
|
||||
save!
|
||||
end
|
||||
end
|
||||
|
||||
def alert_registrar_lock_changes!(lock: true)
|
||||
translation = lock ? 'locked' : 'unlocked'
|
||||
registrar.notifications.create!(
|
||||
text: I18n.t("notifications.texts.registrar_#{translation}",
|
||||
domain_name: name),
|
||||
attached_obj_id: name,
|
||||
attached_obj_type: self.class.name
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
40
app/models/contact_request.rb
Normal file
40
app/models/contact_request.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
class ContactRequest < ApplicationRecord
|
||||
establish_connection :"whois_#{Rails.env}"
|
||||
self.table_name = 'contact_requests'
|
||||
|
||||
STATUS_NEW = 'new'.freeze
|
||||
STATUS_CONFIRMED = 'confirmed'.freeze
|
||||
STATUS_SENT = 'sent'.freeze
|
||||
STATUSES = [STATUS_NEW, STATUS_CONFIRMED, STATUS_SENT].freeze
|
||||
|
||||
validates :whois_record_id, presence: true
|
||||
validates :email, presence: true
|
||||
validates :name, presence: true
|
||||
validates :status, inclusion: { in: STATUSES }
|
||||
|
||||
attr_readonly :secret,
|
||||
:valid_to
|
||||
|
||||
def self.save_record(params)
|
||||
contact_request = new(params)
|
||||
contact_request.secret = create_random_secret
|
||||
contact_request.valid_to = set_valid_to_24_hours_from_now
|
||||
contact_request.status = STATUS_NEW
|
||||
contact_request.save!
|
||||
contact_request
|
||||
end
|
||||
|
||||
def update_status(params)
|
||||
self.status = params['status']
|
||||
self.ip_address = params['ip']
|
||||
save!
|
||||
end
|
||||
|
||||
def self.create_random_secret
|
||||
SecureRandom.hex(64)
|
||||
end
|
||||
|
||||
def self.set_valid_to_24_hours_from_now
|
||||
(Time.zone.now + 24.hours)
|
||||
end
|
||||
end
|
|
@ -107,13 +107,13 @@ class Domain < ApplicationRecord
|
|||
|
||||
validate :status_is_consistant
|
||||
def status_is_consistant
|
||||
has_error = (statuses.include?(DomainStatus::SERVER_HOLD) && statuses.include?(DomainStatus::SERVER_MANUAL_INZONE))
|
||||
unless has_error
|
||||
if (statuses & [DomainStatus::PENDING_DELETE_CONFIRMATION, DomainStatus::PENDING_DELETE, DomainStatus::FORCE_DELETE]).any?
|
||||
has_error = statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED
|
||||
end
|
||||
has_error = (hold_status? && statuses.include?(DomainStatus::SERVER_MANUAL_INZONE))
|
||||
unless has_error
|
||||
if (statuses & DELETE_STATUSES).any?
|
||||
has_error = statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED
|
||||
end
|
||||
errors.add(:domains, I18n.t(:object_status_prohibits_operation)) if has_error
|
||||
end
|
||||
errors.add(:domains, I18n.t(:object_status_prohibits_operation)) if has_error
|
||||
end
|
||||
|
||||
attr_accessor :is_admin
|
||||
|
|
|
@ -42,17 +42,12 @@ class Epp::Contact < Contact
|
|||
)
|
||||
end
|
||||
|
||||
def check_availability(codes)
|
||||
def check_availability(codes, reg:)
|
||||
codes = [codes] if codes.is_a?(String)
|
||||
|
||||
res = []
|
||||
codes.each do |x|
|
||||
contact = find_by_epp_code(x)
|
||||
if contact
|
||||
res << { code: contact.code, avail: 0, reason: 'in use' }
|
||||
else
|
||||
res << { code: x, avail: 1 }
|
||||
end
|
||||
codes.map { |c| c.include?(':') ? c : "#{reg}:#{c}" }.map { |c| c.strip.upcase }.each do |x|
|
||||
c = find_by_epp_code(x)
|
||||
res << (c ? { code: c.code, avail: 0, reason: 'in use' } : { code: x, avail: 1 })
|
||||
end
|
||||
|
||||
res
|
||||
|
@ -87,8 +82,11 @@ class Epp::Contact < Contact
|
|||
'2302' => [ # Object exists
|
||||
[:code, :epp_id_taken]
|
||||
],
|
||||
'2304' => [ # Status prohibits operation
|
||||
[:statuses, :delete_prohibited],
|
||||
],
|
||||
'2305' => [ # Association exists
|
||||
[:domains, :exist]
|
||||
[:domains, :exist],
|
||||
]
|
||||
}
|
||||
end
|
||||
|
|
|
@ -495,7 +495,7 @@ class Epp::Domain < Domain
|
|||
registrant_verification_needed = false
|
||||
# registrant block may not be present, so we need this to rule out false positives
|
||||
if frame.css('registrant').text.present?
|
||||
registrant_verification_needed = (registrant.code != frame.css('registrant').text)
|
||||
registrant_verification_needed = verification_needed?(code: frame.css('registrant').text)
|
||||
end
|
||||
|
||||
if registrant_verification_needed && disputed?
|
||||
|
@ -612,7 +612,6 @@ class Epp::Domain < Domain
|
|||
|
||||
statuses.delete(DomainStatus::SERVER_HOLD)
|
||||
statuses.delete(DomainStatus::EXPIRED)
|
||||
statuses.delete(DomainStatus::SERVER_UPDATE_PROHIBITED)
|
||||
cancel_pending_delete
|
||||
|
||||
save
|
||||
|
@ -798,4 +797,13 @@ class Epp::Domain < Domain
|
|||
result
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def verification_needed?(code:)
|
||||
new_registrant = Registrant.find_by(code: code)
|
||||
return false if new_registrant.try(:identical_to?, registrant)
|
||||
|
||||
registrant.code != code
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,6 +25,10 @@ class Notification < ApplicationRecord
|
|||
''
|
||||
end
|
||||
|
||||
def registry_lock?
|
||||
text.include?('has been locked') || text.include?('has been unlocked')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_defaults
|
||||
|
|
|
@ -4,8 +4,13 @@ class WhiteIp < ApplicationRecord
|
|||
|
||||
validate :valid_ipv4?
|
||||
validate :valid_ipv6?
|
||||
|
||||
validate :validate_ipv4_and_ipv6
|
||||
before_save :normalize_blank_values
|
||||
|
||||
def normalize_blank_values
|
||||
%i[ipv4 ipv6].each { |c| self[c].present? || self[c] = nil }
|
||||
end
|
||||
|
||||
def validate_ipv4_and_ipv6
|
||||
return if ipv4.present? || ipv6.present?
|
||||
errors.add(:base, I18n.t(:ipv4_or_ipv6_must_be_present))
|
||||
|
@ -50,10 +55,10 @@ class WhiteIp < ApplicationRecord
|
|||
def ids_including(ip)
|
||||
ipv4 = ipv6 = []
|
||||
if check_ip4(ip).present?
|
||||
ipv4 = select { |white_ip| IPAddr.new(white_ip.ipv4, Socket::AF_INET) === check_ip4(ip) }
|
||||
ipv4 = select { |white_ip| check_ip4(white_ip.ipv4) === check_ip4(ip) }
|
||||
end
|
||||
if check_ip6(ip).present?
|
||||
ipv6 = select { |white_ip| IPAddr.new(white_ip.ipv6, Socket::AF_INET6) === check_ip6(ip) }
|
||||
ipv6 = select { |white_ip| check_ip6(white_ip.ipv6) === check_ip6(ip) }
|
||||
end
|
||||
(ipv4 + ipv6).pluck(:id).flatten.uniq
|
||||
end
|
||||
|
|
|
@ -97,7 +97,9 @@ class WhoisRecord < ApplicationRecord
|
|||
end
|
||||
|
||||
def destroy_whois_record
|
||||
Whois::Record.without_auctions.where(name: name).delete_all
|
||||
return if Auction.find_by(domain: name).present?
|
||||
|
||||
Whois::Record.where(name: name).delete_all
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -15,12 +15,22 @@ xml.epp_head do
|
|||
end if @object
|
||||
end
|
||||
|
||||
if @notification.action&.contact
|
||||
render(partial: 'epp/poll/action',
|
||||
locals: {
|
||||
builder: xml,
|
||||
action: @notification.action
|
||||
})
|
||||
if @notification.action&.contact || @notification.registry_lock?
|
||||
if @notification.registry_lock?
|
||||
state = @notification.text.include?('unlocked') ? 'unlock' : 'lock'
|
||||
xml.extension do
|
||||
xml.tag!('changePoll:changeData',
|
||||
'xmlns:changePoll': 'https://epp.tld.ee/schema/changePoll-1.0.xsd') do
|
||||
xml.tag!('changePoll:operation', state)
|
||||
end
|
||||
end
|
||||
else
|
||||
render(partial: 'epp/poll/action',
|
||||
locals: {
|
||||
builder: xml,
|
||||
action: @notification.action,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
render('epp/shared/trID', builder: xml)
|
||||
|
|
65
app/views/registrar/bulk_change/_admin_contact_form.html.erb
Normal file
65
app/views/registrar/bulk_change/_admin_contact_form.html.erb
Normal file
|
@ -0,0 +1,65 @@
|
|||
<%= form_tag registrar_admin_contacts_path, method: :patch, class: 'form-horizontal' do %>
|
||||
<% if @error %>
|
||||
<div class="alert alert-danger">
|
||||
<%= @error %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-md-6 control-label">
|
||||
<p><%= t '.comment' %></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2 control-label">
|
||||
<%= label_tag :current_contact_id, t('.current_contact_id') %>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 current_admin_contact">
|
||||
<%= text_field_tag :current_contact_id, params[:current_contact_id],
|
||||
list: :contacts,
|
||||
required: true,
|
||||
autofocus: true,
|
||||
class: 'form-control' %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-2 control-label">
|
||||
<%= label_tag :new_contact_id, t('.new_contact_id') %>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 new_admin_contact">
|
||||
<%= text_field_tag :new_contact_id, params[:new_contact_id],
|
||||
list: :contacts,
|
||||
required: true,
|
||||
class: 'form-control' %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-4 col-md-offset-2 text-right">
|
||||
<button class="btn btn-warning">
|
||||
<%= t '.submit_btn' %>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-6">
|
||||
<a class="btn btn-default btn-xs" role="button" data-toggle="collapse"
|
||||
href="#bulk_change_tech_contact_help"><%= t '.help_btn' %></a>
|
||||
<div class="collapse" id="bulk_change_tech_contact_help">
|
||||
<div class="well">
|
||||
<%= t '.help' %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<datalist id="contacts">
|
||||
<% available_contacts.each do |data| %>
|
||||
<option value="<%= data.second %>"><%= data.first %></option>
|
||||
<% end %>
|
||||
</datalist>
|
|
@ -10,7 +10,7 @@
|
|||
<%= label_tag :current_contact_id, t('.current_contact_id') %>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-4 current_tech_contact">
|
||||
<%= text_field_tag :current_contact_id, params[:current_contact_id],
|
||||
list: :contacts,
|
||||
required: true,
|
||||
|
@ -24,7 +24,7 @@
|
|||
<%= label_tag :new_contact_id, t('.new_contact_id') %>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-4 new_tech_contact">
|
||||
<%= text_field_tag :new_contact_id, params[:new_contact_id],
|
||||
list: :contacts,
|
||||
required: true,
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
<a href="#technical_contact" data-toggle="tab"><%= t '.technical_contact' %></a>
|
||||
</li>
|
||||
|
||||
<li class="<%= 'active' if active_tab == :admin_contact %>">
|
||||
<a href="#admin_contact" data-toggle="tab"><%= t '.admin_contact' %></a>
|
||||
</li>
|
||||
|
||||
<li class="<%= 'active' if active_tab == :nameserver %>">
|
||||
<a href="#nameserver" data-toggle="tab"><%= t '.nameserver' %></a>
|
||||
</li>
|
||||
|
@ -31,6 +35,11 @@
|
|||
<%= render 'tech_contact_form', available_contacts: available_contacts %>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane<%= ' active' if active_tab == :admin_contact %>"
|
||||
id="admin_contact">
|
||||
<%= render 'admin_contact_form', available_contacts: available_contacts %>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane<%= ' active' if active_tab == :nameserver %>" id="nameserver">
|
||||
<%= render 'nameserver_form' %>
|
||||
</div>
|
||||
|
|
|
@ -87,8 +87,11 @@ sk_digi_doc_service_name: 'Testimine'
|
|||
registrant_api_base_url:
|
||||
registrant_api_auth_allowed_ips: '127.0.0.1, 0.0.0.0' #ips, separated with commas
|
||||
|
||||
# Bounces API
|
||||
api_shared_key: testkey
|
||||
# Shared key for REST-WHOIS Bounces API incl. CERT
|
||||
rwhois_bounces_api_shared_key: testkey
|
||||
|
||||
# Link to REST-WHOIS API
|
||||
rwhois_internal_api_shared_key: testkey
|
||||
|
||||
# Base URL (inc. https://) of REST registrant portal
|
||||
# Leave blank to use internal registrant portal
|
||||
|
|
4
config/initializers/aws_ses.rb
Normal file
4
config/initializers/aws_ses.rb
Normal file
|
@ -0,0 +1,4 @@
|
|||
Aws.config.update(
|
||||
region: ENV['aws_default_region'],
|
||||
credentials: Aws::Credentials.new(ENV['aws_access_key_id'], ENV['aws_secret_access_key'])
|
||||
)
|
|
@ -25,8 +25,10 @@ en:
|
|||
email_regex_check_error: Invalid format
|
||||
domains:
|
||||
exist: 'Object association prohibits operation'
|
||||
delete_prohibited: Contact delete prohibited by status
|
||||
statuses:
|
||||
not_uniq: 'not uniq'
|
||||
delete_prohibited: Contact delete prohibited by status
|
||||
country_code:
|
||||
invalid: Country code is not valid, should be in ISO_3166-1 alpha 2 format (%{value})
|
||||
disclosed_attributes:
|
||||
|
|
|
@ -6,3 +6,5 @@ en:
|
|||
It was associated with registrant %{old_registrant_code}
|
||||
and contacts %{old_contacts_codes}.
|
||||
contact_update: Contact %{contact} has been updated by registrant
|
||||
registrar_locked: Domain %{domain_name} has been locked by registrant
|
||||
registrar_unlocked: Domain %{domain_name} has been unlocked by registrant
|
||||
|
|
6
config/locales/registrar/admin_contacts.en.yml
Normal file
6
config/locales/registrar/admin_contacts.en.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
en:
|
||||
registrar:
|
||||
admin_contacts:
|
||||
update:
|
||||
replaced: Admin contacts have been successfully replaced.
|
||||
replaced: Technical contacts have been successfully replaced.
|
11
config/locales/registrar/admin_contacts.yml
Normal file
11
config/locales/registrar/admin_contacts.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
en:
|
||||
registrar:
|
||||
admin_contacts:
|
||||
update:
|
||||
replaced: Admin contacts have been successfully replaced.
|
||||
affected_domains: Affected domains
|
||||
skipped_domains: Skipped domains
|
||||
process_request:
|
||||
affected_domains: Affected domains
|
||||
skipped_domains: Skipped domains
|
||||
replaced: Admin contacts have been successfully replaced.
|
|
@ -4,6 +4,7 @@ en:
|
|||
new:
|
||||
header: Bulk change
|
||||
technical_contact: Technical contact
|
||||
admin_contact: Admin contact
|
||||
nameserver: Nameserver
|
||||
bulk_transfer: Bulk transfer
|
||||
bulk_renew: Bulk renew
|
||||
|
@ -17,6 +18,19 @@ en:
|
|||
Replace technical contact specified in "current contact ID" with the one in "new
|
||||
contact ID" on any domain registered under this registrar
|
||||
|
||||
admin_contact_form:
|
||||
current_contact_id: Current admin contact ID
|
||||
new_contact_id: New admin contact ID
|
||||
submit_btn: Replace admin contacts
|
||||
help_btn: Toggle help
|
||||
help: >-
|
||||
Replace admin contact specified in "current contact ID" with the one in "new
|
||||
contact ID" on any domain registered under this registrar. Contact idents must
|
||||
be the same
|
||||
comment: >-
|
||||
Bulk admin change is only allowed in case of old and new contact are sharing identical
|
||||
ident data ie for updating contact information.
|
||||
|
||||
nameserver_form:
|
||||
ip_hint: One IP per line
|
||||
replace_btn: Replace nameserver
|
||||
|
@ -38,3 +52,5 @@ en:
|
|||
domain_ids: Domains for bulk renewal
|
||||
current_balance: Current balance
|
||||
period: Period
|
||||
affected_domains: Affected domains
|
||||
skipped_domains: Skipped domains
|
||||
|
|
|
@ -5,3 +5,7 @@ en:
|
|||
replaced: Technical contacts have been successfully replaced.
|
||||
affected_domains: Affected domains
|
||||
skipped_domains: Skipped domains
|
||||
process_request:
|
||||
affected_domains: Affected domains
|
||||
skipped_domains: Skipped domains
|
||||
replaced: Technical contacts have been successfully replaced.
|
||||
|
|
|
@ -64,6 +64,7 @@ Rails.application.routes.draw do
|
|||
get ':id/transfer_info', to: 'domains#transfer_info', constraints: { id: /.*/ }
|
||||
post 'transfer', to: 'domains#transfer'
|
||||
patch 'contacts', to: 'domains/contacts#update'
|
||||
patch 'admin_contacts', to: 'domains/admin_contacts#update'
|
||||
post 'renew/bulk', to: 'domains/renews#bulk_renew'
|
||||
end
|
||||
end
|
||||
|
@ -91,6 +92,7 @@ Rails.application.routes.draw do
|
|||
end
|
||||
|
||||
resources :auctions, only: %i[index show update], param: :uuid
|
||||
resources :contact_requests, only: %i[create update], param: :id
|
||||
resources :bounces, only: %i[create]
|
||||
end
|
||||
|
||||
|
@ -136,6 +138,7 @@ Rails.application.routes.draw do
|
|||
resource :bulk_change, controller: :bulk_change, only: :new
|
||||
post '/bulk_renew/new', to: 'bulk_change#bulk_renew', as: :bulk_renew
|
||||
resource :tech_contacts, only: :update
|
||||
resource :admin_contacts, only: :update
|
||||
resource :nameservers, only: :update
|
||||
resources :contacts, constraints: {:id => /[^\/]+(?=#{ ActionController::Renderers::RENDERERS.map{|e| "\\.#{e}\\z"}.join("|") })|[^\/]+/} do
|
||||
member do
|
||||
|
|
30
doc/repp/v1/admin_contacts.md
Normal file
30
doc/repp/v1/admin_contacts.md
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Admin domain contacts
|
||||
|
||||
## PATCH https://repp.internet.ee/v1/domains/admin_contacts
|
||||
Replaces admin domain contacts of the current registrar.
|
||||
|
||||
### Example request
|
||||
```
|
||||
PATCH /repp/v1/domains/admin_contacts HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic dGVzdDp0ZXN0dGVzdA==
|
||||
|
||||
{
|
||||
"current_contact_id": "ATSAA:749AA80F",
|
||||
"new_contact_id": "ATSAA:E36957D7"
|
||||
}
|
||||
```
|
||||
### Example response
|
||||
```
|
||||
{
|
||||
"code": 1000,
|
||||
"message": "Command completed successfully",
|
||||
"data": {
|
||||
"affected_domains": [
|
||||
"private.ee",
|
||||
],
|
||||
"skipped_domains": []
|
||||
}
|
||||
}
|
||||
```
|
|
@ -1,7 +1,7 @@
|
|||
# Domain contacts
|
||||
# Tech domain contacts
|
||||
|
||||
## PATCH https://repp.internet.ee/v1/domains/contacts
|
||||
Replaces all domain contacts of the current registrar.
|
||||
Replaces technical domain contacts of the current registrar.
|
||||
|
||||
### Example request
|
||||
```
|
||||
|
|
8
test/fixtures/contact_requests.yml
vendored
Normal file
8
test/fixtures/contact_requests.yml
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
new:
|
||||
whois_record_id: 1
|
||||
email: aaa@bbb.com
|
||||
name: Testname
|
||||
status: new
|
||||
secret: somesecret
|
||||
valid_to: 2010-07-05
|
||||
|
153
test/integration/api/domain_admin_contacts_test.rb
Normal file
153
test/integration/api/domain_admin_contacts_test.rb
Normal file
|
@ -0,0 +1,153 @@
|
|||
require 'test_helper'
|
||||
|
||||
class APIDomainAdminContactsTest < ApplicationIntegrationTest
|
||||
setup do
|
||||
@admin_current = domains(:shop).admin_contacts.find_by(code: 'jane-001')
|
||||
domain = domains(:airport)
|
||||
domain.admin_contacts << @admin_current
|
||||
@admin_new = contacts(:william)
|
||||
|
||||
@admin_new.update(ident: @admin_current.ident,
|
||||
ident_type: @admin_current.ident_type,
|
||||
ident_country_code: @admin_current.ident_country_code)
|
||||
end
|
||||
|
||||
def test_replace_all_admin_contacts_when_ident_data_doesnt_match
|
||||
@admin_new.update(ident: '777' ,
|
||||
ident_type: 'priv',
|
||||
ident_country_code: 'LV')
|
||||
|
||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||
new_contact_id: @admin_new.code },
|
||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||
|
||||
assert_response :bad_request
|
||||
assert_equal ({ code: 2304, message: 'Admin contacts must be identical', data: {} }),
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
def test_replace_all_admin_contacts_of_the_current_registrar
|
||||
assert @admin_new.identical_to?(@admin_current)
|
||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||
new_contact_id: @admin_new.code },
|
||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||
|
||||
assert_nil domains(:shop).admin_contacts.find_by(code: @admin_current.code)
|
||||
assert domains(:shop).admin_contacts.find_by(code: @admin_new.code)
|
||||
assert domains(:airport).admin_contacts.find_by(code: @admin_new.code)
|
||||
end
|
||||
|
||||
def test_skip_discarded_domains
|
||||
domains(:airport).update!(statuses: [DomainStatus::DELETE_CANDIDATE])
|
||||
|
||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||
new_contact_id: @admin_new.code },
|
||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||
|
||||
assert domains(:airport).admin_contacts.find_by(code: @admin_current.code)
|
||||
end
|
||||
|
||||
def test_return_affected_domains_in_alphabetical_order
|
||||
domain = domains(:airport)
|
||||
domain.admin_contacts = [@admin_current]
|
||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||
new_contact_id: @admin_new.code },
|
||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||
|
||||
assert_response :ok
|
||||
assert_equal ({ code: 1000, message: 'Command completed successfully', data: { 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/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||
new_contact_id: @admin_new.code },
|
||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||
|
||||
assert_response :ok
|
||||
assert_equal %w[airport.test shop.test], JSON.parse(response.body,
|
||||
symbolize_names: true)[:data][:skipped_domains]
|
||||
end
|
||||
|
||||
def test_keep_other_admin_contacts_intact
|
||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||
new_contact_id: @admin_new.code },
|
||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||
|
||||
assert domains(:airport).admin_contacts.find_by(code: 'john-001')
|
||||
end
|
||||
|
||||
def test_keep_tech_contacts_intact
|
||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||
new_contact_id: @admin_new.code },
|
||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||
|
||||
assert domains(:airport).tech_contacts.find_by(code: 'william-001')
|
||||
end
|
||||
|
||||
def test_restrict_contacts_to_the_current_registrar
|
||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||
new_contact_id: 'william-002' },
|
||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||
|
||||
assert_response :not_found
|
||||
assert_equal ({ code: 2303, message: 'Object does not exist' }),
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
def test_non_existent_current_contact
|
||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: 'non-existent',
|
||||
new_contact_id: @admin_new.code},
|
||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||
assert_response :not_found
|
||||
assert_equal ({ code: 2303, message: 'Object does not exist' }),
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
def test_non_existent_new_contact
|
||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||
new_contact_id: 'non-existent' },
|
||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||
assert_response :not_found
|
||||
assert_equal ({code: 2303, message: 'Object does not exist'}),
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
def test_disallow_invalid_new_contact
|
||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||
new_contact_id: 'invalid' },
|
||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||
assert_response :bad_request
|
||||
assert_equal ({ code: 2304, message: 'New contact must be valid', data: {} }),
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
def test_admin_bulk_changed_when_domain_update_prohibited
|
||||
domains(:shop).update!(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED])
|
||||
domains(:airport).admin_contacts = [@admin_current]
|
||||
|
||||
shop_admin_contact = Contact.find_by(code: 'jane-001')
|
||||
assert domains(:shop).admin_contacts.include?(shop_admin_contact)
|
||||
|
||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||
new_contact_id: @admin_new.code },
|
||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||
|
||||
assert_response :ok
|
||||
assert_equal ({ code: 1000,
|
||||
message: 'Command completed successfully',
|
||||
data: { affected_domains: ["airport.test"],
|
||||
skipped_domains: ["shop.test"] }}),
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def http_auth_key
|
||||
ActionController::HttpAuthentication::Basic.encode_credentials('test_bestnames', 'testtest')
|
||||
end
|
||||
end
|
|
@ -2,7 +2,7 @@ require 'test_helper'
|
|||
|
||||
class BouncesApiV1CreateTest < ActionDispatch::IntegrationTest
|
||||
def setup
|
||||
@api_key = "Basic #{ENV['api_shared_key']}"
|
||||
@api_key = "Basic #{ENV['rwhois_bounces_api_shared_key']}"
|
||||
@headers = { "Authorization": "#{@api_key}" }
|
||||
@json_body = { "data": valid_bounce_request }.as_json
|
||||
end
|
||||
|
|
68
test/integration/api/v1/contact_requests_test.rb
Normal file
68
test/integration/api/v1/contact_requests_test.rb
Normal file
|
@ -0,0 +1,68 @@
|
|||
require 'test_helper'
|
||||
|
||||
class ApiV1ContactRequestTest < ActionDispatch::IntegrationTest
|
||||
def setup
|
||||
@api_key = "Basic #{ENV['rwhois_internal_api_shared_key']}"
|
||||
@headers = { "Authorization": "#{@api_key}" }
|
||||
@json_create = { "contact_request": valid_contact_request_create }.as_json
|
||||
@json_update = { "contact_request": valid_contact_request_update }.as_json
|
||||
@contact_request = contact_requests(:new)
|
||||
end
|
||||
|
||||
def test_authorizes_api_request
|
||||
post api_v1_contact_requests_path, params: @json_create, headers: @headers
|
||||
assert_response :created
|
||||
|
||||
invalid_headers = { "Authorization": "Basic invalid_api_key" }
|
||||
post api_v1_contact_requests_path, params: @json_create, headers: invalid_headers
|
||||
assert_response :unauthorized
|
||||
end
|
||||
|
||||
def test_saves_new_contact_request
|
||||
request_body = @json_create.dup
|
||||
random_mail = "#{rand(10000..99999)}@registry.test"
|
||||
request_body['contact_request']['email'] = random_mail
|
||||
|
||||
post api_v1_contact_requests_path, params: request_body, headers: @headers
|
||||
assert_response :created
|
||||
|
||||
contact_request = ContactRequest.last
|
||||
assert_equal contact_request.email, random_mail
|
||||
assert ContactRequest::STATUS_NEW, contact_request.status
|
||||
end
|
||||
|
||||
def test_updates_existing_contact_request
|
||||
request_body = @json_update.dup
|
||||
|
||||
put api_v1_contact_request_path(@contact_request.id), params: request_body, headers: @headers
|
||||
assert_response :ok
|
||||
|
||||
@contact_request.reload
|
||||
assert ContactRequest::STATUS_CONFIRMED, @contact_request.status
|
||||
end
|
||||
|
||||
def test_not_updates_if_status_error
|
||||
request_body = @json_update.dup
|
||||
request_body['contact_request']['status'] = 'some_error_status'
|
||||
|
||||
put api_v1_contact_request_path(@contact_request.id), params: request_body, headers: @headers
|
||||
assert_response 400
|
||||
|
||||
@contact_request.reload
|
||||
assert ContactRequest::STATUS_NEW, @contact_request.status
|
||||
end
|
||||
|
||||
def valid_contact_request_create
|
||||
{
|
||||
"email": "aaa@bbb.com",
|
||||
"whois_record_id": "1",
|
||||
"name": "test"
|
||||
}.as_json
|
||||
end
|
||||
|
||||
def valid_contact_request_update
|
||||
{
|
||||
"status": "#{ContactRequest::STATUS_CONFIRMED}",
|
||||
}.as_json
|
||||
end
|
||||
end
|
|
@ -26,7 +26,7 @@ class EppContactCheckBaseTest < EppTestCase
|
|||
|
||||
response_xml = Nokogiri::XML(response.body)
|
||||
assert_epp_response :completed_successfully
|
||||
assert_equal 'john-001', response_xml.at_xpath('//contact:id', contact: xml_schema).text
|
||||
assert_equal "#{@contact.registrar.code}:JOHN-001".upcase, response_xml.at_xpath('//contact:id', contact: xml_schema).text
|
||||
end
|
||||
|
||||
def test_contact_is_available
|
||||
|
@ -52,7 +52,8 @@ class EppContactCheckBaseTest < EppTestCase
|
|||
end
|
||||
|
||||
def test_contact_is_unavailable
|
||||
assert_equal 'john-001', @contact.code
|
||||
@contact.update_columns(code: "#{@contact.registrar.code}:JOHN-001".upcase)
|
||||
assert @contact.code, "#{@contact.registrar.code}:JOHN-001".upcase
|
||||
|
||||
request_xml = <<-XML
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
|
@ -98,9 +99,61 @@ class EppContactCheckBaseTest < EppTestCase
|
|||
assert_equal 3, response_xml.xpath('//contact:cd', contact: xml_schema).size
|
||||
end
|
||||
|
||||
def test_check_contact_with_prefix
|
||||
@contact.update_columns(code: "#{@contact.registrar.code}:JOHN-001".upcase)
|
||||
assert @contact.code, "#{@contact.registrar.code}:JOHN-001".upcase
|
||||
|
||||
request_xml = <<-XML
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
|
||||
<command>
|
||||
<check>
|
||||
<contact:check xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||
<contact:id>BESTNAMES:JOHN-001</contact:id>
|
||||
</contact:check>
|
||||
</check>
|
||||
</command>
|
||||
</epp>
|
||||
XML
|
||||
|
||||
post epp_check_path, params: { frame: request_xml },
|
||||
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
|
||||
|
||||
response_xml = Nokogiri::XML(response.body)
|
||||
assert_epp_response :completed_successfully
|
||||
assert_equal "#{@contact.registrar.code}:JOHN-001".upcase, response_xml.at_xpath('//contact:id', contact: xml_schema).text
|
||||
assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text
|
||||
end
|
||||
|
||||
def test_check_contact_without_prefix
|
||||
@contact.update_columns(code: "#{@contact.registrar.code}:JOHN-001".upcase)
|
||||
assert @contact.code, "#{@contact.registrar.code}:JOHN-001".upcase
|
||||
|
||||
request_xml = <<-XML
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
|
||||
<command>
|
||||
<check>
|
||||
<contact:check xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||
<contact:id>JOHN-001</contact:id>
|
||||
</contact:check>
|
||||
</check>
|
||||
</command>
|
||||
</epp>
|
||||
XML
|
||||
|
||||
post epp_check_path, params: { frame: request_xml },
|
||||
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
|
||||
|
||||
response_xml = Nokogiri::XML(response.body)
|
||||
assert_epp_response :completed_successfully
|
||||
assert_equal "#{@contact.registrar.code}:JOHN-001".upcase, response_xml.at_xpath('//contact:id', contact: xml_schema).text
|
||||
assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def xml_schema
|
||||
'https://epp.tld.ee/schema/contact-ee-1.1.xsd'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -27,6 +27,60 @@ class EppContactDeleteBaseTest < EppTestCase
|
|||
assert_epp_response :completed_successfully
|
||||
end
|
||||
|
||||
def test_delete_contact_with_server_delete_prohibited
|
||||
contact = deletable_contact
|
||||
contact.update(statuses: Contact::SERVER_DELETE_PROHIBITED)
|
||||
assert contact.statuses.include? Contact::SERVER_DELETE_PROHIBITED
|
||||
|
||||
contact.update_columns(code: contact.code.upcase)
|
||||
|
||||
request_xml = <<-XML
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
|
||||
<command>
|
||||
<delete>
|
||||
<contact:delete xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||
<contact:id>#{contact.code.upcase}</contact:id>
|
||||
</contact:delete>
|
||||
</delete>
|
||||
</command>
|
||||
</epp>
|
||||
XML
|
||||
|
||||
post epp_delete_path, params: { frame: request_xml },
|
||||
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
|
||||
|
||||
assert Contact.exists?(id: contact.id)
|
||||
assert_epp_response :object_status_prohibits_operation
|
||||
end
|
||||
|
||||
def test_delete_contact_with_client_delete_prohibited
|
||||
contact = deletable_contact
|
||||
contact.update(statuses: Contact::CLIENT_DELETE_PROHIBITED)
|
||||
assert contact.statuses.include? Contact::CLIENT_DELETE_PROHIBITED
|
||||
|
||||
contact.update_columns(code: contact.code.upcase)
|
||||
|
||||
request_xml = <<-XML
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
|
||||
<command>
|
||||
<delete>
|
||||
<contact:delete xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||
<contact:id>#{contact.code.upcase}</contact:id>
|
||||
</contact:delete>
|
||||
</delete>
|
||||
</command>
|
||||
</epp>
|
||||
XML
|
||||
|
||||
post epp_delete_path, params: { frame: request_xml },
|
||||
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
|
||||
|
||||
assert Contact.exists?(id: contact.id)
|
||||
assert_epp_response :object_status_prohibits_operation
|
||||
end
|
||||
|
||||
def test_undeletable_cannot_be_deleted
|
||||
contact = contacts(:john)
|
||||
assert_not contact.deletable?
|
||||
|
@ -61,4 +115,4 @@ class EppContactDeleteBaseTest < EppTestCase
|
|||
DomainContact.delete_all
|
||||
contacts(:john)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -44,6 +44,58 @@ class EppContactInfoBaseTest < EppTestCase
|
|||
contact: xml_schema).text
|
||||
end
|
||||
|
||||
def test_get_info_about_contact_with_prefix
|
||||
@contact.update_columns(code: 'TEST:JOHN-001')
|
||||
assert @contact.code, 'TEST:JOHN-001'
|
||||
|
||||
request_xml = <<-XML
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
|
||||
<command>
|
||||
<info>
|
||||
<contact:info xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||
<contact:id>TEST:JOHN-001</contact:id>
|
||||
</contact:info>
|
||||
</info>
|
||||
</command>
|
||||
</epp>
|
||||
XML
|
||||
|
||||
post epp_info_path, params: { frame: request_xml },
|
||||
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
|
||||
|
||||
response_xml = Nokogiri::XML(response.body)
|
||||
assert_epp_response :completed_successfully
|
||||
assert_equal 'TEST:JOHN-001', response_xml.at_xpath('//contact:id', contact: xml_schema).text
|
||||
assert_equal '+555.555', response_xml.at_xpath('//contact:voice', contact: xml_schema).text
|
||||
end
|
||||
|
||||
def test_get_info_about_contact_without_prefix
|
||||
@contact.update_columns(code: "#{@contact.registrar.code}:JOHN-001".upcase)
|
||||
assert @contact.code, "#{@contact.registrar.code}:JOHN-001".upcase
|
||||
|
||||
request_xml = <<-XML
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
|
||||
<command>
|
||||
<info>
|
||||
<contact:info xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||
<contact:id>JOHN-001</contact:id>
|
||||
</contact:info>
|
||||
</info>
|
||||
</command>
|
||||
</epp>
|
||||
XML
|
||||
|
||||
post epp_info_path, params: { frame: request_xml },
|
||||
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
|
||||
|
||||
response_xml = Nokogiri::XML(response.body)
|
||||
assert_epp_response :completed_successfully
|
||||
assert_equal "#{@contact.registrar.code}:JOHN-001".upcase, response_xml.at_xpath('//contact:id', contact: xml_schema).text
|
||||
assert_equal '+555.555', response_xml.at_xpath('//contact:voice', contact: xml_schema).text
|
||||
end
|
||||
|
||||
def test_hides_password_and_name_when_current_registrar_is_not_sponsoring
|
||||
non_sponsoring_registrar = registrars(:goodnames)
|
||||
@contact.update!(registrar: non_sponsoring_registrar)
|
||||
|
|
|
@ -123,6 +123,46 @@ class EppDomainUpdateBaseTest < EppTestCase
|
|||
assert_verification_and_notification_emails
|
||||
end
|
||||
|
||||
def test_domain_should_doesnt_have_pending_update_when_updated_registrant_with_same_idents_data
|
||||
assert_not @domain.statuses.include? "pendingUpdate"
|
||||
|
||||
old_registrant = @domain.registrant
|
||||
new_registrant = contacts(:william).becomes(Registrant)
|
||||
|
||||
new_registrant.update(ident: old_registrant.ident)
|
||||
new_registrant.update(ident_country_code: old_registrant.ident_country_code)
|
||||
new_registrant.update(ident_type: old_registrant.ident_type)
|
||||
|
||||
request_xml = <<-XML
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
|
||||
<command>
|
||||
<update>
|
||||
<domain:update xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
|
||||
<domain:name>#{@domain.name}</domain:name>
|
||||
<domain:chg>
|
||||
<domain:registrant verified="no">#{new_registrant.code}</domain:registrant>
|
||||
</domain:chg>
|
||||
</domain:update>
|
||||
</update>
|
||||
<extension>
|
||||
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
|
||||
<eis:legalDocument type="pdf">#{'test' * 2000}</eis:legalDocument>
|
||||
</eis:extdata>
|
||||
</extension>
|
||||
</command>
|
||||
</epp>
|
||||
XML
|
||||
|
||||
post epp_update_path, params: { frame: request_xml },
|
||||
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
|
||||
@domain.reload
|
||||
assert_epp_response :completed_successfully
|
||||
|
||||
assert_equal @domain.registrant, new_registrant
|
||||
assert_not @domain.statuses.include? "pendingUpdate"
|
||||
end
|
||||
|
||||
def test_requires_verification_from_current_registrant_when_not_yet_verified_by_registrar
|
||||
Setting.request_confirmation_on_registrant_change_enabled = true
|
||||
new_registrant = contacts(:william)
|
||||
|
|
|
@ -37,6 +37,29 @@ class ReppV1DomainsBulkRenewTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
end
|
||||
|
||||
def test_keeps_update_prohibited_status
|
||||
domain = domains(:shop)
|
||||
domain.update(statuses: [DomainStatus::CLIENT_UPDATE_PROHIBITED, DomainStatus::SERVER_UPDATE_PROHIBITED])
|
||||
payload = {
|
||||
"domains": [
|
||||
'shop.test'
|
||||
],
|
||||
"renew_period": "1y"
|
||||
}
|
||||
|
||||
assert_changes -> { Domain.find_by(name: 'shop.test').valid_to } do
|
||||
post "/repp/v1/domains/renew/bulk", headers: @auth_headers, params: payload
|
||||
json = JSON.parse(response.body, symbolize_names: true)
|
||||
|
||||
assert_response :ok
|
||||
assert_equal 1000, json[:code]
|
||||
assert_equal 'Command completed successfully', json[:message]
|
||||
assert json[:data][:updated_domains].include? 'shop.test'
|
||||
end
|
||||
domain.reload
|
||||
assert_equal domain.statuses, [DomainStatus::CLIENT_UPDATE_PROHIBITED, DomainStatus::SERVER_UPDATE_PROHIBITED]
|
||||
end
|
||||
|
||||
def test_throws_error_when_domain_not_renewable
|
||||
payload = {
|
||||
"domains": [
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
require "test_helper"
|
||||
|
||||
class DomainUpdateConfirmJobTest < ActiveSupport::TestCase
|
||||
def setup
|
||||
super
|
||||
|
@ -19,6 +18,22 @@ class DomainUpdateConfirmJobTest < ActiveSupport::TestCase
|
|||
super
|
||||
end
|
||||
|
||||
def test_registrant_locked_domain
|
||||
refute @domain.locked_by_registrant?
|
||||
@domain.apply_registry_lock
|
||||
assert @domain.locked_by_registrant?
|
||||
assert_equal(@domain.registrar.notifications.last.text, "Domain #{@domain.name} has been locked by registrant")
|
||||
end
|
||||
|
||||
def test_registrant_unlocked_domain
|
||||
refute @domain.locked_by_registrant?
|
||||
@domain.apply_registry_lock
|
||||
assert @domain.locked_by_registrant?
|
||||
@domain.remove_registry_lock
|
||||
refute @domain.locked_by_registrant?
|
||||
assert_equal(@domain.registrar.notifications.last.text, "Domain #{@domain.name} has been unlocked by registrant")
|
||||
end
|
||||
|
||||
def test_rejected_registrant_verification_notifies_registrar
|
||||
DomainUpdateConfirmJob.perform_now(@domain.id, RegistrantVerification::REJECTED)
|
||||
|
||||
|
|
|
@ -234,6 +234,19 @@ class ForceDeleteTest < ActionMailer::TestCase
|
|||
assert_includes(@domain.statuses, asserted_status)
|
||||
end
|
||||
|
||||
def test_client_hold_prohibits_manual_inzone
|
||||
@domain.update(valid_to: Time.zone.parse('2012-08-05'))
|
||||
@domain.update(template_name: 'legal_person')
|
||||
travel_to Time.zone.parse('2010-07-05')
|
||||
@domain.schedule_force_delete(type: :soft)
|
||||
travel_to Time.zone.parse('2010-08-21')
|
||||
Domains::ClientHold::SetClientHold.run!
|
||||
@domain.reload
|
||||
|
||||
@domain.statuses << DomainStatus::SERVER_MANUAL_INZONE
|
||||
assert_not @domain.valid?
|
||||
end
|
||||
|
||||
def test_force_delete_soft_year_ahead_not_sets_client_hold_before_threshold
|
||||
asserted_status = DomainStatus::CLIENT_HOLD
|
||||
|
||||
|
|
|
@ -38,6 +38,20 @@ class WhiteIpTest < ActiveSupport::TestCase
|
|||
assert white_ip.valid?
|
||||
end
|
||||
|
||||
def test_validates_include_empty_ipv4
|
||||
white_ip = WhiteIp.new
|
||||
|
||||
white_ip.ipv4 = nil
|
||||
white_ip.ipv6 = '001:0db8:85a3:0000:0000:8a2e:0370:7334'
|
||||
white_ip.registrar = registrars(:bestnames)
|
||||
|
||||
assert_nothing_raised { white_ip.save }
|
||||
assert white_ip.valid?
|
||||
|
||||
assert WhiteIp.include_ip?(white_ip.ipv6)
|
||||
assert_not WhiteIp.include_ip?('192.168.1.1')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def valid_white_ip
|
||||
|
|
49
test/system/registrar_area/bulk_change/admin_contact_test.rb
Normal file
49
test/system/registrar_area/bulk_change/admin_contact_test.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
require 'application_system_test_case'
|
||||
|
||||
class RegistrarAreaAdminContactBulkChangeTest < ApplicationSystemTestCase
|
||||
setup do
|
||||
sign_in users(:api_bestnames)
|
||||
end
|
||||
|
||||
def test_replace_domain_contacts_of_current_registrar
|
||||
request_stub = stub_request(:patch, /domains\/admin_contacts/)
|
||||
.with(body: { current_contact_id: 'william-001', new_contact_id: 'john-001' },
|
||||
basic_auth: ['test_bestnames', 'testtest'])
|
||||
.to_return(body: { data: { 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'
|
||||
click_link 'Admin contact'
|
||||
|
||||
find('.current_admin_contact').fill_in 'Current contact ID', with: 'william-001'
|
||||
find('.new_admin_contact').fill_in 'New contact ID', with: 'john-001'
|
||||
click_on 'Replace admin contacts'
|
||||
|
||||
assert_requested request_stub
|
||||
assert_current_path registrar_domains_path
|
||||
assert_text 'Admin 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\/admin_contacts/)
|
||||
.to_return(status: 400,
|
||||
body: { message: 'epic fail' }.to_json,
|
||||
headers: { 'Content-type' => Mime[:json] })
|
||||
|
||||
visit registrar_domains_url
|
||||
click_link 'Bulk change'
|
||||
click_link 'Admin contact'
|
||||
|
||||
find('.current_admin_contact').fill_in 'Current contact ID', with: 'william-001'
|
||||
find('.new_admin_contact').fill_in 'New contact ID', with: 'john-001'
|
||||
click_on 'Replace admin contacts'
|
||||
|
||||
assert_text 'epic fail'
|
||||
assert_field 'Current contact ID', with: 'william-001'
|
||||
assert_field 'New contact ID', with: 'john-001'
|
||||
end
|
||||
end
|
|
@ -16,8 +16,8 @@ class RegistrarAreaTechContactBulkChangeTest < ApplicationSystemTestCase
|
|||
visit registrar_domains_url
|
||||
click_link 'Bulk change'
|
||||
|
||||
fill_in 'Current contact ID', with: 'william-001'
|
||||
fill_in 'New contact ID', with: 'john-001'
|
||||
find('.current_tech_contact').fill_in 'Current contact ID', with: 'william-001'
|
||||
find('.new_tech_contact').fill_in 'New contact ID', with: 'john-001'
|
||||
click_on 'Replace technical contacts'
|
||||
|
||||
assert_requested request_stub
|
||||
|
@ -36,8 +36,8 @@ class RegistrarAreaTechContactBulkChangeTest < ApplicationSystemTestCase
|
|||
visit registrar_domains_url
|
||||
click_link 'Bulk change'
|
||||
|
||||
fill_in 'Current contact ID', with: 'william-001'
|
||||
fill_in 'New contact ID', with: 'john-001'
|
||||
find('.current_tech_contact').fill_in 'Current contact ID', with: 'william-001'
|
||||
find('.new_tech_contact').fill_in 'New contact ID', with: 'john-001'
|
||||
click_on 'Replace technical contacts'
|
||||
|
||||
assert_text 'epic fail'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue