mirror of
https://github.com/internetee/registry.git
synced 2025-06-07 13:15:40 +02:00
Merge remote-tracking branch 'origin/master' into repp-domains
This commit is contained in:
commit
43e5b74668
29 changed files with 357 additions and 49 deletions
7
.github/workflows/ruby.yml
vendored
7
.github/workflows/ruby.yml
vendored
|
@ -17,7 +17,7 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-18.04]
|
os: [ubuntu-18.04]
|
||||||
ruby: [2.6, 2.7 ]
|
ruby: [ 2.7 ]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
|
continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
|
||||||
steps:
|
steps:
|
||||||
|
@ -100,11 +100,6 @@ jobs:
|
||||||
- name: Give test coverage reporter executable permissions
|
- name: Give test coverage reporter executable permissions
|
||||||
run: chmod +x cc-test-reporter
|
run: chmod +x cc-test-reporter
|
||||||
|
|
||||||
- uses: actions/download-artifact@v1
|
|
||||||
with:
|
|
||||||
name: coverage-2.6
|
|
||||||
path: coverage
|
|
||||||
|
|
||||||
- uses: actions/download-artifact@v1
|
- uses: actions/download-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: coverage-2.7
|
name: coverage-2.7
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
2.6.5
|
2.7.2
|
||||||
|
|
21
CHANGELOG.md
21
CHANGELOG.md
|
@ -1,3 +1,24 @@
|
||||||
|
28.01.2021
|
||||||
|
* Fixed transfer with shared admin and tech contacts [#1808](https://github.com/internetee/registry/issues/1808)
|
||||||
|
* Improved DNSSEC key validation for illegal characters [#1790](https://github.com/internetee/registry/issues/1790)
|
||||||
|
* Fix for whois record creation issue on releasing domain to auction [#1139](https://github.com/internetee/registry/issues/1139)
|
||||||
|
* Improved registrar account activity tests [#1824](https://github.com/internetee/registry/pull/1824)
|
||||||
|
|
||||||
|
27.01.2021
|
||||||
|
* Figaro update to 1.2.0 [#1823](https://github.com/internetee/registry/pull/1823)
|
||||||
|
|
||||||
|
26.01.2021
|
||||||
|
* Ruby update to 2.7 [#1791](https://github.com/internetee/registry/issues/1791)
|
||||||
|
|
||||||
|
21.01.2021
|
||||||
|
* Registrant API: optimised contact linking [#1807](https://github.com/internetee/registry/pull/1807)
|
||||||
|
|
||||||
|
20.01.2021
|
||||||
|
* Fixed legaldoc assignment issue on registrant confirmation [#1806](https://github.com/internetee/registry/pull/1806)
|
||||||
|
|
||||||
|
14.01.2021
|
||||||
|
* Fixed IDN and punycode support for REPP domain transfer_info request [#1801](https://github.com/internetee/registry/issues/1801)
|
||||||
|
|
||||||
06.01.2021
|
06.01.2021
|
||||||
* IMproved tests whois update for bulk nameserver change [#1739](https://github.com/internetee/registry/issues/1739)
|
* IMproved tests whois update for bulk nameserver change [#1739](https://github.com/internetee/registry/issues/1739)
|
||||||
* Bulk ForceDelete funcionality in admin [#1177](https://github.com/internetee/registry/issues/1177)
|
* Bulk ForceDelete funcionality in admin [#1177](https://github.com/internetee/registry/issues/1177)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM internetee/ruby:2.6-buster
|
FROM internetee/ruby:2.7-buster
|
||||||
|
|
||||||
RUN mkdir -p /opt/webapps/app/tmp/pids
|
RUN mkdir -p /opt/webapps/app/tmp/pids
|
||||||
WORKDIR /opt/webapps/app
|
WORKDIR /opt/webapps/app
|
||||||
|
|
2
Gemfile
2
Gemfile
|
@ -10,7 +10,7 @@ gem 'rest-client'
|
||||||
gem 'uglifier'
|
gem 'uglifier'
|
||||||
|
|
||||||
# load env
|
# load env
|
||||||
gem 'figaro', '1.1.1'
|
gem 'figaro', '~> 1.2'
|
||||||
|
|
||||||
# model related
|
# model related
|
||||||
gem 'activerecord-import'
|
gem 'activerecord-import'
|
||||||
|
|
|
@ -204,8 +204,8 @@ GEM
|
||||||
erubis (2.7.0)
|
erubis (2.7.0)
|
||||||
execjs (2.7.0)
|
execjs (2.7.0)
|
||||||
ffi (1.13.1)
|
ffi (1.13.1)
|
||||||
figaro (1.1.1)
|
figaro (1.2.0)
|
||||||
thor (~> 0.14)
|
thor (>= 0.14.0, < 2)
|
||||||
globalid (0.4.2)
|
globalid (0.4.2)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
gyoku (1.3.1)
|
gyoku (1.3.1)
|
||||||
|
@ -506,7 +506,7 @@ DEPENDENCIES
|
||||||
e_invoice!
|
e_invoice!
|
||||||
epp!
|
epp!
|
||||||
epp-xml (= 1.1.0)!
|
epp-xml (= 1.1.0)!
|
||||||
figaro (= 1.1.1)
|
figaro (~> 1.2)
|
||||||
haml (~> 5.0)
|
haml (~> 5.0)
|
||||||
isikukood
|
isikukood
|
||||||
iso8601 (= 0.12.1)
|
iso8601 (= 0.12.1)
|
||||||
|
|
|
@ -24,7 +24,7 @@ module Api
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
contact = current_user_contacts.find_by(uuid: params[:uuid])
|
contact = representable_contact(params[:uuid])
|
||||||
links = params[:links] == 'true'
|
links = params[:links] == 'true'
|
||||||
|
|
||||||
if contact
|
if contact
|
||||||
|
@ -91,6 +91,22 @@ module Api
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def representable_contact(uuid)
|
||||||
|
country = current_registrant_user.country.alpha2
|
||||||
|
contact = Contact.find_by(uuid: uuid, ident: current_registrant_user.ident,
|
||||||
|
ident_type: 'priv', ident_country_code: country)
|
||||||
|
return contact if contact
|
||||||
|
|
||||||
|
Contact.find_by(uuid: uuid, ident_type: 'org', ident: company_codes,
|
||||||
|
ident_country_code: country)
|
||||||
|
rescue CompanyRegister::NotAvailableError
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def company_codes
|
||||||
|
current_registrant_user.companies.collect(&:registration_number)
|
||||||
|
end
|
||||||
|
|
||||||
def current_user_contacts
|
def current_user_contacts
|
||||||
current_registrant_user.contacts(representable: false)
|
current_registrant_user.contacts(representable: false)
|
||||||
rescue CompanyRegister::NotAvailableError
|
rescue CompanyRegister::NotAvailableError
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module Repp
|
module Repp
|
||||||
module V1
|
module V1
|
||||||
class BaseController < ActionController::API # rubocop:disable Metrics/ClassLength
|
class BaseController < ActionController::API # rubocop:disable Metrics/ClassLength
|
||||||
rescue_from ActiveRecord::RecordNotFound, with: :not_found_error
|
around_action :log_request
|
||||||
before_action :authenticate_user
|
before_action :authenticate_user
|
||||||
before_action :validate_webclient_ca
|
before_action :validate_webclient_ca
|
||||||
before_action :check_ip_restriction
|
before_action :check_ip_restriction
|
||||||
|
@ -9,22 +9,31 @@ module Repp
|
||||||
|
|
||||||
before_action :set_paper_trail_whodunnit
|
before_action :set_paper_trail_whodunnit
|
||||||
|
|
||||||
rescue_from ActionController::ParameterMissing, Apipie::ParamInvalid,
|
private
|
||||||
Apipie::ParamMissing do |exception|
|
|
||||||
render json: { code: 2003, message: exception }, status: :bad_request
|
def log_request
|
||||||
|
yield
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
@response = { code: 2303, message: 'Object does not exist' }
|
||||||
|
render(json: @response, status: :not_found)
|
||||||
|
rescue ActionController::ParameterMissing, Apipie::ParamInvalid, Apipie::ParamMissing => e
|
||||||
|
@response = { code: 2003, message: e }
|
||||||
|
render(json: @response, status: :bad_request)
|
||||||
|
ensure
|
||||||
|
create_repp_log
|
||||||
end
|
end
|
||||||
|
|
||||||
after_action do
|
# rubocop:disable Metrics/AbcSize
|
||||||
|
def create_repp_log
|
||||||
ApiLog::ReppLog.create(
|
ApiLog::ReppLog.create(
|
||||||
request_path: request.path, request_method: request.request_method,
|
request_path: request.path, request_method: request.request_method,
|
||||||
request_params: request.params.except('route_info').to_json, uuid: request.try(:uuid),
|
request_params: request.params.except('route_info').to_json, uuid: request.try(:uuid),
|
||||||
response: @response.to_json, response_code: status, ip: request.ip,
|
response: @response.to_json, response_code: response.status, ip: request.ip,
|
||||||
api_user_name: current_user.try(:username),
|
api_user_name: current_user.try(:username),
|
||||||
api_user_registrar: current_user.try(:registrar).try(:to_s)
|
api_user_registrar: current_user.try(:registrar).try(:to_s)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
# rubocop:enable Metrics/AbcSize
|
||||||
private
|
|
||||||
|
|
||||||
def set_domain
|
def set_domain
|
||||||
registrar = current_user.registrar
|
registrar = current_user.registrar
|
||||||
|
@ -131,11 +140,6 @@ module Repp
|
||||||
|
|
||||||
render(json: @response, status: :unauthorized)
|
render(json: @response, status: :unauthorized)
|
||||||
end
|
end
|
||||||
|
|
||||||
def not_found_error
|
|
||||||
@response = { code: 2303, message: 'Object does not exist' }
|
|
||||||
render(json: @response, status: :not_found)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,7 @@ module Repp
|
||||||
module V1
|
module V1
|
||||||
class DomainsController < BaseController # rubocop:disable Metrics/ClassLength
|
class DomainsController < BaseController # rubocop:disable Metrics/ClassLength
|
||||||
before_action :set_authorized_domain, only: %i[transfer_info destroy]
|
before_action :set_authorized_domain, only: %i[transfer_info destroy]
|
||||||
|
before_action :validate_registrar_authorization, only: %i[transfer_info destroy]
|
||||||
before_action :forward_registrar_id, only: %i[create destroy]
|
before_action :forward_registrar_id, only: %i[create destroy]
|
||||||
before_action :set_domain, only: %i[show update]
|
before_action :set_domain, only: %i[show update]
|
||||||
|
|
||||||
|
@ -182,11 +183,7 @@ module Repp
|
||||||
|
|
||||||
def set_authorized_domain
|
def set_authorized_domain
|
||||||
@epp_errors ||= []
|
@epp_errors ||= []
|
||||||
h = {}
|
@domain = domain_from_url_hash
|
||||||
h[transfer_info_params[:id].match?(/\A[0-9]+\z/) ? :id : :name] = transfer_info_params[:id]
|
|
||||||
@domain = Epp::Domain.find_by!(h)
|
|
||||||
|
|
||||||
validate_registrar_authorization
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_registrar_authorization
|
def validate_registrar_authorization
|
||||||
|
@ -197,6 +194,13 @@ module Repp
|
||||||
handle_errors
|
handle_errors
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def domain_from_url_hash
|
||||||
|
entry = transfer_info_params[:id]
|
||||||
|
return Domain.find(entry) if entry.match?(/\A[0-9]+\z/)
|
||||||
|
|
||||||
|
Domain.find_by!('name = ? OR name_puny = ?', entry, entry)
|
||||||
|
end
|
||||||
|
|
||||||
def limit
|
def limit
|
||||||
index_params[:limit] || 200
|
index_params[:limit] || 200
|
||||||
end
|
end
|
||||||
|
|
6
app/lib/to_stdout.rb
Normal file
6
app/lib/to_stdout.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
class ToStdout
|
||||||
|
def self.msg(message)
|
||||||
|
time = Time.zone.now.utc
|
||||||
|
STDOUT << "#{time} - #{message}\n" unless Rails.env.test?
|
||||||
|
end
|
||||||
|
end
|
|
@ -68,7 +68,25 @@ module Actions
|
||||||
domain.registrar = current_registrar
|
domain.registrar = current_registrar
|
||||||
assign_domain_period
|
assign_domain_period
|
||||||
assign_domain_auth_codes
|
assign_domain_auth_codes
|
||||||
domain.dnskeys_attributes = params[:dnskeys_attributes] if params[:dnskeys_attributes]
|
assign_dnskeys
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign_dnskeys
|
||||||
|
return unless params[:dnskeys_attributes]&.any?
|
||||||
|
|
||||||
|
params[:dnskeys_attributes].each { |dk| verify_public_key_integrity(dk) }
|
||||||
|
params.dnskeys_attributes = params[:dnskeys_attributes]
|
||||||
|
end
|
||||||
|
|
||||||
|
def verify_public_key_integrity(dnssec)
|
||||||
|
return if dnssec[:public_key].blank?
|
||||||
|
|
||||||
|
value = dnssec[:public_key]
|
||||||
|
if !value.is_a?(String) || Base64.strict_encode64(Base64.strict_decode64(value)) != value
|
||||||
|
domain.add_epp_error(2005, nil, nil, %i[dnskeys invalid])
|
||||||
|
end
|
||||||
|
rescue ArgumentError
|
||||||
|
domain.add_epp_error(2005, nil, nil, %i[dnskeys invalid])
|
||||||
end
|
end
|
||||||
|
|
||||||
def assign_domain_auth_codes
|
def assign_domain_auth_codes
|
||||||
|
|
|
@ -92,18 +92,20 @@ module Actions
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_dnskey_integrity(key)
|
def validate_dnskey_integrity(key)
|
||||||
if key[:pubKey] && !Setting.key_data_allowed
|
if key[:public_key] && !Setting.key_data_allowed
|
||||||
domain.add_epp_error('2306', nil, nil, %i[dnskeys key_data_not_allowed])
|
domain.add_epp_error('2306', nil, nil, %i[dnskeys key_data_not_allowed])
|
||||||
elsif key[:digest] && !Setting.ds_data_allowed
|
elsif key[:ds_digest] && !Setting.ds_data_allowed
|
||||||
domain.add_epp_error('2306', nil, nil, %i[dnskeys ds_data_not_allowed])
|
domain.add_epp_error('2306', nil, nil, %i[dnskeys ds_data_not_allowed])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
verify_public_key_integrity(key)
|
||||||
|
|
||||||
@dnskeys << key.except(:action)
|
@dnskeys << key.except(:action)
|
||||||
end
|
end
|
||||||
|
|
||||||
def assign_removable_dnskey(key)
|
def assign_removable_dnskey(key)
|
||||||
dnkey = domain.dnskeys.find_by(key.except(:action))
|
dnkey = domain.dnskeys.find_by(key.except(:action))
|
||||||
domain.add_epp_error('2303', nil, nil, %i[dnskeys not_found]) unless dnkey
|
domain.add_epp_error(2303, nil, nil, %i[dnskeys not_found]) unless dnkey
|
||||||
|
|
||||||
@dnskeys << { id: dnkey.id, _destroy: 1 } if dnkey
|
@dnskeys << { id: dnkey.id, _destroy: 1 } if dnkey
|
||||||
end
|
end
|
||||||
|
@ -240,5 +242,16 @@ module Actions
|
||||||
|
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def verify_public_key_integrity(dnssec)
|
||||||
|
return if dnssec[:public_key].blank?
|
||||||
|
|
||||||
|
value = dnssec[:public_key]
|
||||||
|
if !value.is_a?(String) || Base64.strict_encode64(Base64.strict_decode64(value)) != value
|
||||||
|
domain.add_epp_error('2005', nil, nil, %i[dnskeys invalid])
|
||||||
|
end
|
||||||
|
rescue ArgumentError
|
||||||
|
domain.add_epp_error('2005', nil, nil, %i[dnskeys invalid])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -39,13 +39,15 @@ module Concerns
|
||||||
|
|
||||||
def release
|
def release
|
||||||
if release_to_auction
|
if release_to_auction
|
||||||
transaction do
|
ToStdout.msg 'Destroying domain'
|
||||||
domain_name.sell_at_auction if domain_name.auctionable?
|
destroy!
|
||||||
destroy!
|
ToStdout.msg "Checking if domain_name is auctionable: #{domain_name.auctionable?}"
|
||||||
registrar.notifications.create!(text: "#{I18n.t(:domain_deleted)}: #{name}",
|
domain_name.sell_at_auction if domain_name.auctionable?
|
||||||
attached_obj_id: id,
|
|
||||||
attached_obj_type: self.class)
|
ToStdout.msg 'Sending registrar notification'
|
||||||
end
|
registrar.notifications.create!(text: "#{I18n.t(:domain_deleted)}: #{name}",
|
||||||
|
attached_obj_id: id,
|
||||||
|
attached_obj_type: self.class)
|
||||||
else
|
else
|
||||||
discard
|
discard
|
||||||
end
|
end
|
||||||
|
|
|
@ -59,7 +59,7 @@ module Concerns::Domain::Transferable
|
||||||
copied_ids = []
|
copied_ids = []
|
||||||
domain_contacts.each do |dc|
|
domain_contacts.each do |dc|
|
||||||
contact = Contact.find(dc.contact_id)
|
contact = Contact.find(dc.contact_id)
|
||||||
next if copied_ids.include?(contact.id) || contact.registrar == new_registrar
|
next if copied_ids.include?(uniq_contact_hash(dc)) || contact.registrar == new_registrar
|
||||||
|
|
||||||
if registrant_id_was == contact.id # registrant was copied previously, do not copy it again
|
if registrant_id_was == contact.id # registrant was copied previously, do not copy it again
|
||||||
oc = OpenStruct.new(id: registrant_id)
|
oc = OpenStruct.new(id: registrant_id)
|
||||||
|
@ -72,7 +72,11 @@ module Concerns::Domain::Transferable
|
||||||
else
|
else
|
||||||
dc.update(contact_id: oc.id)
|
dc.update(contact_id: oc.id)
|
||||||
end
|
end
|
||||||
copied_ids << contact.id
|
copied_ids << uniq_contact_hash(dc)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def uniq_contact_hash(contact)
|
||||||
|
Digest::SHA1.hexdigest(contact.contact_id.to_s + contact.type)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -360,9 +360,11 @@ class Contact < ApplicationRecord
|
||||||
@desc
|
@desc
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Limits returned objects to 11
|
||||||
def related_domains
|
def related_domains
|
||||||
a = related_domain_descriptions
|
ids = DomainContact.select(:domain_id).where(contact_id: id).limit(11).map(&:domain_id).uniq
|
||||||
a.keys.map { |d| { name: d, id: a[d][:id], roles: a[d][:roles] } }
|
res = Domain.where(id: ids).or(Domain.where(registrant_id: id)).select(:name, :uuid).limit(11)
|
||||||
|
res.pluck(:name, :uuid).map { |name, id| { name: name, id: id } }
|
||||||
end
|
end
|
||||||
|
|
||||||
def status_notes_array=(notes)
|
def status_notes_array=(notes)
|
||||||
|
|
|
@ -36,6 +36,7 @@ module DNS
|
||||||
auction = Auction.new
|
auction = Auction.new
|
||||||
auction.domain = name
|
auction.domain = name
|
||||||
auction.start
|
auction.start
|
||||||
|
ToStdout.msg "Created the auction: #{auction.inspect}"
|
||||||
update_whois_from_auction(auction)
|
update_whois_from_auction(auction)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -100,7 +101,8 @@ module DNS
|
||||||
whois_record = Whois::Record.find_or_create_by!(name: name) do |record|
|
whois_record = Whois::Record.find_or_create_by!(name: name) do |record|
|
||||||
record.json = {}
|
record.json = {}
|
||||||
end
|
end
|
||||||
|
ToStdout.msg "Starting to update WHOIS record #{whois_record.inspect}\n\n"\
|
||||||
|
"from auction #{auction.inspect}"
|
||||||
whois_record.update_from_auction(auction)
|
whois_record.update_from_auction(auction)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -78,7 +78,7 @@ class Domain < ApplicationRecord
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
after_commit :update_whois_record, unless: -> { domain_name.at_auction? }
|
after_commit :update_whois_record
|
||||||
|
|
||||||
after_create :update_reserved_domains
|
after_create :update_reserved_domains
|
||||||
def update_reserved_domains
|
def update_reserved_domains
|
||||||
|
|
|
@ -128,6 +128,7 @@ class Epp::Domain < Domain
|
||||||
|
|
||||||
def attach_legal_document(legal_document_data)
|
def attach_legal_document(legal_document_data)
|
||||||
return unless legal_document_data
|
return unless legal_document_data
|
||||||
|
return unless legal_document_data[:body]
|
||||||
return if legal_document_data[:body].starts_with?(ENV['legal_documents_dir'])
|
return if legal_document_data[:body].starts_with?(ENV['legal_documents_dir'])
|
||||||
|
|
||||||
legal_documents.create(
|
legal_documents.create(
|
||||||
|
|
|
@ -2,23 +2,34 @@ module Whois
|
||||||
class Record < Whois::Server
|
class Record < Whois::Server
|
||||||
self.table_name = 'whois_records'
|
self.table_name = 'whois_records'
|
||||||
|
|
||||||
|
def self.without_auctions
|
||||||
|
ids = Whois::Record.all.select { |record| Auction.where(domain: record.name).blank? }
|
||||||
|
.pluck(:id)
|
||||||
|
Whois::Record.where(id: ids)
|
||||||
|
end
|
||||||
|
|
||||||
def self.disclaimer
|
def self.disclaimer
|
||||||
Setting.registry_whois_disclaimer
|
Setting.registry_whois_disclaimer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# rubocop:disable Metrics/AbcSize
|
||||||
def update_from_auction(auction)
|
def update_from_auction(auction)
|
||||||
if auction.started?
|
if auction.started?
|
||||||
update!(json: { name: auction.domain,
|
update!(json: { name: auction.domain,
|
||||||
status: ['AtAuction'],
|
status: ['AtAuction'],
|
||||||
disclaimer: self.class.disclaimer })
|
disclaimer: self.class.disclaimer })
|
||||||
|
ToStdout.msg "Updated from auction WHOIS record #{inspect}"
|
||||||
elsif auction.no_bids?
|
elsif auction.no_bids?
|
||||||
|
ToStdout.msg "Destroying WHOIS record #{inspect}"
|
||||||
destroy!
|
destroy!
|
||||||
elsif auction.awaiting_payment? || auction.payment_received?
|
elsif auction.awaiting_payment? || auction.payment_received?
|
||||||
update!(json: { name: auction.domain,
|
update!(json: { name: auction.domain,
|
||||||
status: ['PendingRegistration'],
|
status: ['PendingRegistration'],
|
||||||
disclaimer: self.class.disclaimer,
|
disclaimer: self.class.disclaimer,
|
||||||
registration_deadline: auction.whois_deadline })
|
registration_deadline: auction.whois_deadline })
|
||||||
|
ToStdout.msg "Updated from auction WHOIS record #{inspect}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
# rubocop:enable Metrics/AbcSize
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -97,7 +97,7 @@ class WhoisRecord < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy_whois_record
|
def destroy_whois_record
|
||||||
Whois::Record.where(name: name).delete_all
|
Whois::Record.without_auctions.where(name: name).delete_all
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -36,8 +36,10 @@ module DomainNameRegistry
|
||||||
|
|
||||||
# Autoload all model subdirs
|
# Autoload all model subdirs
|
||||||
config.autoload_paths += Dir[Rails.root.join('app', 'models', '**/')]
|
config.autoload_paths += Dir[Rails.root.join('app', 'models', '**/')]
|
||||||
|
config.autoload_paths += Dir[Rails.root.join('app', 'lib', '**/')]
|
||||||
config.autoload_paths += Dir[Rails.root.join('app', 'interactions', '**/')]
|
config.autoload_paths += Dir[Rails.root.join('app', 'interactions', '**/')]
|
||||||
config.eager_load_paths << config.root.join('lib', 'validators')
|
config.eager_load_paths << config.root.join('lib', 'validators')
|
||||||
|
config.eager_load_paths << config.root.join('app', 'lib')
|
||||||
config.watchable_dirs['lib'] = %i[rb]
|
config.watchable_dirs['lib'] = %i[rb]
|
||||||
|
|
||||||
config.active_record.schema_format = :sql
|
config.active_record.schema_format = :sql
|
||||||
|
|
|
@ -5,6 +5,7 @@ module I18n
|
||||||
alias_method :original_localize, :localize
|
alias_method :original_localize, :localize
|
||||||
|
|
||||||
def localize(object, options = {})
|
def localize(object, options = {})
|
||||||
|
options.merge!({ default: '-' })
|
||||||
object.present? ? original_localize(object, options) : ''
|
object.present? ? original_localize(object, options) : ''
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -57,6 +57,15 @@ class RegistrantApiContactsTest < ApplicationIntegrationTest
|
||||||
assert_equal({ errors: [base: ['Not authorized']] }, json_body)
|
assert_equal({ errors: [base: ['Not authorized']] }, json_body)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_gets_contact_domain_links_when_requested
|
||||||
|
get "/api/v1/registrant/contacts/#{@contact.uuid}?links=true", headers: @auth_headers
|
||||||
|
|
||||||
|
expected_links = @contact.domains.uniq.map { |d| { name: d.name, id: d.uuid }}
|
||||||
|
assert_response :ok
|
||||||
|
response_json = JSON.parse(response.body, symbolize_names: true)
|
||||||
|
|
||||||
|
assert_empty expected_links - response_json[:links]
|
||||||
|
end
|
||||||
private
|
private
|
||||||
|
|
||||||
def auth_token
|
def auth_token
|
||||||
|
|
|
@ -2,6 +2,51 @@ require 'test_helper'
|
||||||
|
|
||||||
class EppDomainCreateBaseTest < EppTestCase
|
class EppDomainCreateBaseTest < EppTestCase
|
||||||
|
|
||||||
|
def test_illegal_chars_in_dns_key
|
||||||
|
name = "new.#{dns_zones(:one).origin}"
|
||||||
|
contact = contacts(:john)
|
||||||
|
registrant = contact.becomes(Registrant)
|
||||||
|
|
||||||
|
pub_key = "AwEAAddt2AkLf\n
|
||||||
|
\n
|
||||||
|
YGKgiEZB5SmIF8E\n
|
||||||
|
vrjxNMH6HtxW\rEA4RJ9Ao6LCWheg8"
|
||||||
|
|
||||||
|
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>
|
||||||
|
<create>
|
||||||
|
<domain:create xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
|
||||||
|
<domain:name>#{name}</domain:name>
|
||||||
|
<domain:registrant>#{registrant.code}</domain:registrant>
|
||||||
|
</domain:create>
|
||||||
|
</create>
|
||||||
|
<extension>
|
||||||
|
<secDNS:create xmlns:secDNS="urn:ietf:params:xml:ns:secDNS-1.1">
|
||||||
|
<secDNS:keyData>
|
||||||
|
<secDNS:flags>257</secDNS:flags>
|
||||||
|
<secDNS:protocol>3</secDNS:protocol>
|
||||||
|
<secDNS:alg>8</secDNS:alg>
|
||||||
|
<secDNS:pubKey>#{pub_key}</secDNS:pubKey>
|
||||||
|
</secDNS:keyData>
|
||||||
|
</secDNS:create>
|
||||||
|
<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
|
||||||
|
assert_no_difference 'Domain.count' do
|
||||||
|
post epp_create_path, params: { frame: request_xml },
|
||||||
|
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_epp_response :parameter_value_syntax_error
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def test_not_registers_domain_without_legaldoc
|
def test_not_registers_domain_without_legaldoc
|
||||||
now = Time.zone.parse('2010-07-05')
|
now = Time.zone.parse('2010-07-05')
|
||||||
travel_to now
|
travel_to now
|
||||||
|
|
|
@ -3,6 +3,7 @@ require 'test_helper'
|
||||||
class EppDomainTransferRequestTest < EppTestCase
|
class EppDomainTransferRequestTest < EppTestCase
|
||||||
def setup
|
def setup
|
||||||
@domain = domains(:shop)
|
@domain = domains(:shop)
|
||||||
|
@contact = contacts(:jane)
|
||||||
@new_registrar = registrars(:goodnames)
|
@new_registrar = registrars(:goodnames)
|
||||||
@original_transfer_wait_time = Setting.transfer_wait_time
|
@original_transfer_wait_time = Setting.transfer_wait_time
|
||||||
Setting.transfer_wait_time = 0
|
Setting.transfer_wait_time = 0
|
||||||
|
@ -12,6 +13,95 @@ class EppDomainTransferRequestTest < EppTestCase
|
||||||
Setting.transfer_wait_time = @original_transfer_wait_time
|
Setting.transfer_wait_time = @original_transfer_wait_time
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_transfer_domain_with_contacts_if_registrant_and_tech_are_shared
|
||||||
|
@domain.tech_domain_contacts[0].update!(contact_id: @domain.registrant.id)
|
||||||
|
|
||||||
|
@domain.tech_domain_contacts[1].delete
|
||||||
|
@domain.reload
|
||||||
|
|
||||||
|
post epp_transfer_path, params: { frame: request_xml },
|
||||||
|
headers: { 'HTTP_COOKIE' => 'session=api_goodnames' }
|
||||||
|
|
||||||
|
assert_epp_response :completed_successfully
|
||||||
|
|
||||||
|
@domain.reload
|
||||||
|
|
||||||
|
tech = Contact.find_by(id: @domain.tech_domain_contacts[0].contact_id)
|
||||||
|
|
||||||
|
assert_equal @domain.contacts.where(original_id: @domain.registrant.original_id).count, 1
|
||||||
|
assert_equal tech.registrar_id, @domain.registrar.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_transfer_domain_with_contacts_if_registrant_and_admin_are_shared
|
||||||
|
@domain.admin_domain_contacts[0].update!(contact_id: @domain.registrant.id)
|
||||||
|
@domain.tech_domain_contacts[0].update!(contact_id: @contact.id)
|
||||||
|
|
||||||
|
@domain.tech_domain_contacts[1].delete
|
||||||
|
@domain.reload
|
||||||
|
|
||||||
|
post epp_transfer_path, params: { frame: request_xml },
|
||||||
|
headers: { 'HTTP_COOKIE' => 'session=api_goodnames' }
|
||||||
|
|
||||||
|
assert_epp_response :completed_successfully
|
||||||
|
|
||||||
|
@domain.reload
|
||||||
|
|
||||||
|
admin = Contact.find_by(id: @domain.admin_domain_contacts[0].contact_id)
|
||||||
|
|
||||||
|
assert_equal @domain.contacts.where(original_id: @domain.registrant.original_id).count, 1
|
||||||
|
assert_equal admin.registrar_id, @domain.registrar.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_transfer_domain_with_contacts_if_admin_and_tech_are_shared
|
||||||
|
@domain.admin_domain_contacts[0].update!(contact_id: @contact.id)
|
||||||
|
@domain.tech_domain_contacts[0].update!(contact_id: @contact.id)
|
||||||
|
|
||||||
|
@domain.tech_domain_contacts[1].delete
|
||||||
|
@domain.reload
|
||||||
|
|
||||||
|
post epp_transfer_path, params: { frame: request_xml },
|
||||||
|
headers: { 'HTTP_COOKIE' => 'session=api_goodnames' }
|
||||||
|
|
||||||
|
assert_epp_response :completed_successfully
|
||||||
|
|
||||||
|
@domain.reload
|
||||||
|
|
||||||
|
admin = Contact.find_by(id: @domain.admin_domain_contacts[0].contact_id)
|
||||||
|
tech = Contact.find_by(id: @domain.tech_domain_contacts[0].contact_id)
|
||||||
|
|
||||||
|
result_hash = @domain.contacts.pluck(:original_id).group_by(&:itself).transform_values(&:count)
|
||||||
|
assert result_hash[admin.original_id], 2
|
||||||
|
|
||||||
|
assert_equal admin.registrar_id, @domain.registrar.id
|
||||||
|
assert_equal tech.registrar_id, @domain.registrar.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_transfer_domain_with_contacts_if_admin_and_tech_and_registrant_are_shared
|
||||||
|
@domain.tech_domain_contacts[0].update!(contact_id: @domain.registrant.id)
|
||||||
|
@domain.admin_domain_contacts[0].update!(contact_id: @domain.registrant.id)
|
||||||
|
|
||||||
|
@domain.tech_domain_contacts[1].delete
|
||||||
|
@domain.reload
|
||||||
|
|
||||||
|
post epp_transfer_path, params: { frame: request_xml },
|
||||||
|
headers: { 'HTTP_COOKIE' => 'session=api_goodnames' }
|
||||||
|
|
||||||
|
assert_epp_response :completed_successfully
|
||||||
|
|
||||||
|
@domain.reload
|
||||||
|
|
||||||
|
admin = Contact.find_by(id: @domain.admin_domain_contacts[0].contact_id)
|
||||||
|
tech = Contact.find_by(id: @domain.tech_domain_contacts[0].contact_id)
|
||||||
|
|
||||||
|
assert_equal @domain.contacts.where(original_id: @domain.registrant.original_id).count, 2
|
||||||
|
|
||||||
|
result_hash = @domain.contacts.pluck(:original_id).group_by(&:itself).transform_values(&:count)
|
||||||
|
assert result_hash[@domain.registrant.original_id], 2
|
||||||
|
|
||||||
|
assert_equal admin.registrar_id, @domain.registrar.id
|
||||||
|
assert_equal tech.registrar_id, @domain.registrar.id
|
||||||
|
end
|
||||||
|
|
||||||
def test_transfers_domain_at_once
|
def test_transfers_domain_at_once
|
||||||
post epp_transfer_path, params: { frame: request_xml },
|
post epp_transfer_path, params: { frame: request_xml },
|
||||||
headers: { 'HTTP_COOKIE' => 'session=api_goodnames' }
|
headers: { 'HTTP_COOKIE' => 'session=api_goodnames' }
|
||||||
|
|
|
@ -38,4 +38,17 @@ class ReppV1DomainsTransferInfoTest < ActionDispatch::IntegrationTest
|
||||||
assert_equal 'Authorization error', json[:message]
|
assert_equal 'Authorization error', json[:message]
|
||||||
assert_empty json[:data]
|
assert_empty json[:data]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_processes_puny_domains
|
||||||
|
@domain.update(name_puny: 'xn--prototp-s2aa.ee')
|
||||||
|
|
||||||
|
headers = @auth_headers
|
||||||
|
headers['Auth-Code'] = @domain.transfer_code
|
||||||
|
|
||||||
|
get "/repp/v1/domains/xn--prototp-s2aa.ee/transfer_info", headers: headers
|
||||||
|
json = JSON.parse(response.body, symbolize_names: true)
|
||||||
|
|
||||||
|
assert_response :ok
|
||||||
|
assert_equal 1000, json[:code]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,6 +25,7 @@ class DomainReleasableAuctionableTest < ActiveSupport::TestCase
|
||||||
def test_skips_auction_when_domains_is_blocked
|
def test_skips_auction_when_domains_is_blocked
|
||||||
assert_equal 'shop.test', @domain.name
|
assert_equal 'shop.test', @domain.name
|
||||||
blocked_domains(:one).update!(name: 'shop.test')
|
blocked_domains(:one).update!(name: 'shop.test')
|
||||||
|
@domain.save!(validate: false)
|
||||||
|
|
||||||
@domain.release
|
@domain.release
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ class DomainReleasableAuctionableTest < ActiveSupport::TestCase
|
||||||
def test_skips_auction_when_domains_is_reserved
|
def test_skips_auction_when_domains_is_reserved
|
||||||
assert_equal 'shop.test', @domain.name
|
assert_equal 'shop.test', @domain.name
|
||||||
reserved_domains(:one).update!(name: 'shop.test')
|
reserved_domains(:one).update!(name: 'shop.test')
|
||||||
|
@domain.save!(validate: false)
|
||||||
|
|
||||||
@domain.release
|
@domain.release
|
||||||
|
|
||||||
|
@ -58,6 +60,24 @@ class DomainReleasableAuctionableTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_updates_whois_server
|
||||||
|
@domain.update!(delete_date: '2010-07-04')
|
||||||
|
travel_to Time.zone.parse('2010-07-05')
|
||||||
|
old_whois = @domain.whois_record
|
||||||
|
|
||||||
|
Domain.release_domains
|
||||||
|
|
||||||
|
assert_raises ActiveRecord::RecordNotFound do
|
||||||
|
old_whois.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
whois_record = Whois::Record.find_by(name: @domain.name)
|
||||||
|
json = { "name"=>@domain.name,
|
||||||
|
"status"=>["AtAuction"],
|
||||||
|
"disclaimer"=> Setting.registry_whois_disclaimer }
|
||||||
|
assert_equal whois_record.json, json
|
||||||
|
end
|
||||||
|
|
||||||
def test_notifies_registrar
|
def test_notifies_registrar
|
||||||
@domain.update!(delete_date: '2010-07-04')
|
@domain.update!(delete_date: '2010-07-04')
|
||||||
travel_to Time.zone.parse('2010-07-05')
|
travel_to Time.zone.parse('2010-07-05')
|
||||||
|
|
|
@ -20,6 +20,7 @@ class AdminAreaPricesTest < ApplicationSystemTestCase
|
||||||
fill_in 'Valid from', with: effective_date
|
fill_in 'Valid from', with: effective_date
|
||||||
click_on 'Create price'
|
click_on 'Create price'
|
||||||
|
|
||||||
|
|
||||||
assert_text 'Price has been created'
|
assert_text 'Price has been created'
|
||||||
assert_text I18n.localize(effective_date)
|
assert_text I18n.localize(effective_date)
|
||||||
end
|
end
|
||||||
|
|
28
test/system/registrar_area/account_activities_test.rb
Normal file
28
test/system/registrar_area/account_activities_test.rb
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
require 'application_system_test_case'
|
||||||
|
|
||||||
|
class RegistrarAccountActivitiesTest < ApplicationSystemTestCase
|
||||||
|
setup do
|
||||||
|
@registrar = registrars(:bestnames)
|
||||||
|
sign_in users(:api_bestnames)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_show_account_activity_page
|
||||||
|
account_activities(:one).update(sum: "123.00")
|
||||||
|
visit registrar_account_activities_path
|
||||||
|
assert_text 'Account activity'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_download_account_activity
|
||||||
|
now = Time.zone.parse('2010-07-05 08:00')
|
||||||
|
travel_to now
|
||||||
|
account_activities(:one).update(sum: "123.00")
|
||||||
|
|
||||||
|
get registrar_account_activities_path(format: :csv)
|
||||||
|
|
||||||
|
assert_response :ok
|
||||||
|
assert_equal "text/csv", response.headers['Content-Type']
|
||||||
|
assert_equal %(attachment; filename="account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv"; filename*=UTF-8''account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv),
|
||||||
|
response.headers['Content-Disposition']
|
||||||
|
assert_not_empty response.body
|
||||||
|
end
|
||||||
|
end
|
Loading…
Add table
Add a link
Reference in a new issue