mirror of
https://github.com/internetee/registry.git
synced 2025-06-10 14:44:47 +02:00
Merge remote-tracking branch 'origin/registry-660' into registry-661
# Conflicts: # db/structure.sql # doc/repp-doc.md
This commit is contained in:
commit
56e3f236bc
156 changed files with 2085 additions and 1276 deletions
|
@ -54,14 +54,14 @@ class Ability
|
|||
# can(:create, :epp_request)
|
||||
|
||||
# Epp::Domain
|
||||
can(:info, Epp::Domain) { |d, pw| d.registrar_id == @user.registrar_id || pw.blank? ? true : d.auth_info == pw }
|
||||
can(:info, Epp::Domain) { |d, pw| d.registrar_id == @user.registrar_id || pw.blank? ? true : d.transfer_code == pw }
|
||||
can(:check, Epp::Domain)
|
||||
can(:create, Epp::Domain)
|
||||
can(:renew, Epp::Domain) { |d| d.registrar_id == @user.registrar_id }
|
||||
can(:update, Epp::Domain) { |d, pw| d.registrar_id == @user.registrar_id || d.auth_info == pw }
|
||||
can(:transfer, Epp::Domain) { |d, pw| d.auth_info == pw }
|
||||
can(:view_password, Epp::Domain) { |d, pw| d.registrar_id == @user.registrar_id || d.auth_info == pw }
|
||||
can(:delete, Epp::Domain) { |d, pw| d.registrar_id == @user.registrar_id || d.auth_info == pw }
|
||||
can(:update, Epp::Domain) { |d, pw| d.registrar_id == @user.registrar_id || d.transfer_code == pw }
|
||||
can(:transfer, Epp::Domain) { |d, pw| d.transfer_code == pw }
|
||||
can(:view_password, Epp::Domain) { |d, pw| d.registrar_id == @user.registrar_id || d.transfer_code == pw }
|
||||
can(:delete, Epp::Domain) { |d, pw| d.registrar_id == @user.registrar_id || d.transfer_code == pw }
|
||||
|
||||
# Epp::Contact
|
||||
can(:info, Epp::Contact) { |c, pw| c.registrar_id == @user.registrar_id || pw.blank? ? true : c.auth_info == pw }
|
||||
|
|
|
@ -19,24 +19,17 @@ authentication using electronic ID. Association through a business organisation
|
|||
=end
|
||||
|
||||
class BusinessRegistryCache < ActiveRecord::Base
|
||||
|
||||
# 1. load domains by business
|
||||
# 2. load domains by person
|
||||
def associated_contacts
|
||||
contact_ids = Contact.where(ident_type: 'org', ident: associated_businesses, ident_country_code: 'EE').pluck(:id)
|
||||
contact_ids += Contact.where(ident_type: 'priv', ident: ident, ident_country_code: ident_country_code).pluck(:id)
|
||||
contact_ids
|
||||
end
|
||||
|
||||
def associated_domain_ids
|
||||
contact_ids = Contact.where(ident_type: 'org', ident: associated_businesses, ident_country_code: ident_country_code).pluck(:id)
|
||||
contact_ids += Contact.where(ident_type: 'priv', ident: ident, ident_country_code: ident_country_code).pluck(:id)
|
||||
domain_ids = []
|
||||
|
||||
contact_ids = associated_contacts
|
||||
|
||||
unless contact_ids.blank?
|
||||
domain_ids = DomainContact.distinct.where(contact_id: contact_ids).pluck(:domain_id)
|
||||
end
|
||||
|
||||
domain_ids += Domain.where(registrant_id: contact_ids).pluck(:id)
|
||||
|
||||
domain_ids
|
||||
end
|
||||
|
||||
|
@ -69,15 +62,5 @@ class BusinessRegistryCache < ActiveRecord::Base
|
|||
def business_registry
|
||||
Soap::Arireg.new
|
||||
end
|
||||
|
||||
def purge
|
||||
STDOUT << "#{Time.zone.now.utc} - Starting Purge of old BusinessRegistry data from cache\n" unless Rails.env.test?
|
||||
purged = 0
|
||||
BusinessRegistryCache.where('retrieved_on < ?',
|
||||
Time.zone.now < Setting.days_to_keep_business_registry_cache.days).each do |br|
|
||||
br.destroy and purged += 1
|
||||
end
|
||||
STDOUT << "#{Time.zone.now.utc} - Finished purging #{purged} old BusinessRegistry cache items\n" unless Rails.env.test?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
28
app/models/concerns/contact/transferable.rb
Normal file
28
app/models/concerns/contact/transferable.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
module Concerns::Contact::Transferable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
validates :auth_info, presence: true
|
||||
after_initialize :generate_auth_info, if: 'new_record? && auth_info.blank?'
|
||||
end
|
||||
|
||||
def transfer(new_registrar)
|
||||
new_contact = self.dup
|
||||
new_contact.registrar = new_registrar
|
||||
new_contact.original = self
|
||||
new_contact.code = nil
|
||||
new_contact.regenerate_code
|
||||
new_contact.regenerate_auth_info
|
||||
new_contact.remove_address unless self.class.address_processing?
|
||||
new_contact.save!
|
||||
new_contact
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def generate_auth_info
|
||||
self.auth_info = SecureRandom.hex(11)
|
||||
end
|
||||
|
||||
alias_method :regenerate_auth_info, :generate_auth_info
|
||||
end
|
68
app/models/concerns/domain/transferable.rb
Normal file
68
app/models/concerns/domain/transferable.rb
Normal file
|
@ -0,0 +1,68 @@
|
|||
module Concerns::Domain::Transferable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
after_initialize :generate_transfer_code, if: 'new_record? && transfer_code.blank?'
|
||||
end
|
||||
|
||||
def transfer(new_registrar)
|
||||
old_registrar = registrar
|
||||
|
||||
self.registrar = new_registrar
|
||||
regenerate_transfer_code
|
||||
|
||||
contact_codes = contacts.pluck(:code).sort.uniq
|
||||
registrant_code = registrant.code
|
||||
|
||||
transaction do
|
||||
old_registrar.messages.create!(
|
||||
body: I18n.t('domain_transfer_was_approved', contacts: contact_codes, registrant: registrant_code),
|
||||
attached_obj_id: id,
|
||||
attached_obj_type: self.class.name
|
||||
)
|
||||
|
||||
domain_transfers.create!(
|
||||
transfer_requested_at: Time.zone.now,
|
||||
old_registrar: old_registrar,
|
||||
new_registrar: new_registrar
|
||||
)
|
||||
|
||||
transfer_contacts(new_registrar)
|
||||
save!
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_transfer_code
|
||||
self.transfer_code = SecureRandom.hex
|
||||
end
|
||||
|
||||
alias_method :regenerate_transfer_code, :generate_transfer_code
|
||||
|
||||
def transfer_contacts(new_registrar)
|
||||
transfer_registrant(new_registrar)
|
||||
transfer_domain_contacts(new_registrar)
|
||||
end
|
||||
|
||||
def transfer_registrant(new_registrar)
|
||||
return if registrant.registrar == new_registrar
|
||||
self.registrant = registrant.transfer(new_registrar)
|
||||
end
|
||||
|
||||
def transfer_domain_contacts(new_registrar)
|
||||
copied_ids = []
|
||||
contacts.each do |contact|
|
||||
next if copied_ids.include?(contact.id) || contact.registrar == new_registrar
|
||||
|
||||
if registrant_id_was == contact.id # registrant was copied previously, do not copy it again
|
||||
oc = OpenStruct.new(id: registrant_id)
|
||||
else
|
||||
oc = contact.transfer(new_registrar)
|
||||
end
|
||||
|
||||
domain_contacts.where(contact_id: contact.id).update_all({ contact_id: oc.id }) # n+1 workaround
|
||||
copied_ids << contact.id
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,7 +2,9 @@ class Contact < ActiveRecord::Base
|
|||
include Versions # version/contact_version.rb
|
||||
include EppErrors
|
||||
include UserEvents
|
||||
include Concerns::Contact::Transferable
|
||||
|
||||
belongs_to :original, class_name: self.name
|
||||
belongs_to :registrar, required: true
|
||||
has_many :domain_contacts
|
||||
has_many :domains, through: :domain_contacts
|
||||
|
@ -43,7 +45,6 @@ class Contact < ActiveRecord::Base
|
|||
|
||||
before_validation :to_upcase_country_code
|
||||
before_validation :strip_email
|
||||
before_create :generate_auth_info
|
||||
before_update :manage_emails
|
||||
|
||||
composed_of :identifier,
|
||||
|
@ -79,7 +80,6 @@ class Contact < ActiveRecord::Base
|
|||
PASSPORT = 'passport'
|
||||
|
||||
attr_accessor :deliver_emails
|
||||
attr_accessor :domain_transfer # hack but solves problem faster
|
||||
|
||||
#
|
||||
# STATUSES
|
||||
|
@ -313,16 +313,6 @@ class Contact < ActiveRecord::Base
|
|||
!org?
|
||||
end
|
||||
|
||||
def generate_auth_info
|
||||
return if @generate_auth_info_disabled
|
||||
return if auth_info.present?
|
||||
self.auth_info = SecureRandom.hex(11)
|
||||
end
|
||||
|
||||
# def auth_info=(pw)
|
||||
# self[:auth_info] = pw if new_record?
|
||||
# end
|
||||
|
||||
def code=(code)
|
||||
self[:code] = code if new_record? # cannot change code later
|
||||
end
|
||||
|
@ -346,6 +336,8 @@ class Contact < ActiveRecord::Base
|
|||
end
|
||||
# rubocop:enable Metrics/CyclomaticComplexity
|
||||
|
||||
alias_method :regenerate_code, :generate_code
|
||||
|
||||
def country
|
||||
Country.new(country_code)
|
||||
end
|
||||
|
|
|
@ -118,7 +118,7 @@ module Depp
|
|||
|
||||
current_user.request(epp_xml.transfer({
|
||||
name: { value: params[:domain_name] },
|
||||
authInfo: { pw: { value: params[:password] } }
|
||||
authInfo: { pw: { value: params[:transfer_code] } }
|
||||
}, op, Domain.construct_custom_params_hash(params)))
|
||||
end
|
||||
|
||||
|
|
|
@ -36,39 +36,6 @@ module Depp
|
|||
Nokogiri::XML(e.response_xml.to_s).remove_namespaces!
|
||||
end
|
||||
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
def repp_request(path, params = {})
|
||||
client_cert = File.read(ENV['cert_path'])
|
||||
client_key = File.read(ENV['key_path'])
|
||||
|
||||
repp_url = Rails.env.test? ? 'http://localhost:8989/repp/v1/' : ENV['repp_url']
|
||||
uri = URI.parse("#{repp_url}#{path}")
|
||||
uri.query = URI.encode_www_form(params)
|
||||
|
||||
req = Net::HTTP::Get.new(uri)
|
||||
req.basic_auth tag, password
|
||||
|
||||
res = 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(req)
|
||||
end
|
||||
|
||||
ret = OpenStruct.new(code: res.code)
|
||||
ret.parsed_body = JSON.parse(res.body) if res.body.present?
|
||||
|
||||
if ret.parsed_body && ret.parsed_body['error']
|
||||
ret.message = ret.parsed_body['error']
|
||||
else
|
||||
ret.message = res.message
|
||||
end
|
||||
|
||||
ret
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
|
||||
private
|
||||
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
|
|
|
@ -6,6 +6,7 @@ class Domain < ActiveRecord::Base
|
|||
include Concerns::Domain::Activatable
|
||||
include Concerns::Domain::ForceDelete
|
||||
include Concerns::Domain::Deletable
|
||||
include Concerns::Domain::Transferable
|
||||
|
||||
has_paper_trail class_name: "DomainVersion", meta: { children: :children_log }
|
||||
|
||||
|
@ -79,9 +80,7 @@ class Domain < ActiveRecord::Base
|
|||
self.status_notes = {} if status_notes.nil?
|
||||
end
|
||||
|
||||
before_create :generate_auth_info
|
||||
before_create -> { self.reserved = in_reserved_list?; nil }
|
||||
|
||||
before_save :manage_automatic_statuses
|
||||
before_save :touch_always_version
|
||||
def touch_always_version
|
||||
|
@ -105,6 +104,7 @@ class Domain < ActiveRecord::Base
|
|||
validates :name_dirty, domain_name: true, uniqueness: true
|
||||
validates :puny_label, length: { maximum: 63 }
|
||||
validates :period, presence: true, numericality: { only_integer: true }
|
||||
validates :transfer_code, presence: true
|
||||
|
||||
validate :validate_reservation
|
||||
def validate_reservation
|
||||
|
@ -497,19 +497,6 @@ class Domain < ActiveRecord::Base
|
|||
Registrant.find_by(id: pending_json['new_registrant_id'])
|
||||
end
|
||||
|
||||
def generate_auth_info
|
||||
return if auth_info.present?
|
||||
generate_auth_info!
|
||||
end
|
||||
|
||||
# rubocop:disable Lint/Loop
|
||||
def generate_auth_info!
|
||||
begin
|
||||
self.auth_info = SecureRandom.hex
|
||||
end while self.class.exists?(auth_info: auth_info)
|
||||
end
|
||||
# rubocop:enable Lint/Loop
|
||||
|
||||
def set_graceful_expired
|
||||
self.outzone_at = expire_time + self.class.expire_warning_period
|
||||
self.delete_at = outzone_at + self.class.redemption_grace_period
|
||||
|
@ -672,6 +659,12 @@ class Domain < ActiveRecord::Base
|
|||
pending_json['new_registrant_id']
|
||||
end
|
||||
|
||||
def as_json(_options)
|
||||
hash = super
|
||||
hash['auth_info'] = hash.delete('transfer_code') # API v1 requirement
|
||||
hash
|
||||
end
|
||||
|
||||
def self.to_csv
|
||||
CSV.generate do |csv|
|
||||
csv << column_names
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
class DomainTransfer < ActiveRecord::Base
|
||||
include Versions # version/domain_transfer_version.rb
|
||||
belongs_to :domain
|
||||
|
||||
belongs_to :transfer_from, class_name: 'Registrar'
|
||||
belongs_to :transfer_to, class_name: 'Registrar'
|
||||
belongs_to :old_registrar, class_name: 'Registrar'
|
||||
belongs_to :new_registrar, class_name: 'Registrar'
|
||||
|
||||
PENDING = 'pending'
|
||||
CLIENT_APPROVED = 'clientApproved'
|
||||
CLIENT_CANCELLED = 'clientCancelled'
|
||||
CLIENT_REJECTED = 'clientRejected'
|
||||
SERVER_APPROVED = 'serverApproved'
|
||||
SERVER_CANCELLED = 'serverCancelled'
|
||||
|
||||
before_create :set_wait_until
|
||||
def set_wait_until
|
||||
|
@ -39,20 +36,8 @@ class DomainTransfer < ActiveRecord::Base
|
|||
status == PENDING
|
||||
end
|
||||
|
||||
def approve_as_client
|
||||
transaction do
|
||||
self.status = DomainTransfer::CLIENT_APPROVED
|
||||
self.transferred_at = Time.zone.now
|
||||
save
|
||||
|
||||
domain.generate_auth_info
|
||||
domain.registrar = transfer_to
|
||||
domain.save(validate: false)
|
||||
end
|
||||
end
|
||||
|
||||
def notify_losing_registrar(contacts, registrant)
|
||||
transfer_from.messages.create!(
|
||||
old_registrar.messages.create!(
|
||||
body: I18n.t('domain_transfer_was_approved', contacts: contacts, registrant: registrant),
|
||||
attached_obj_id: id,
|
||||
attached_obj_type: self.class.to_s
|
||||
|
|
|
@ -100,7 +100,7 @@ class Epp::Domain < Domain
|
|||
[:puny_label, :too_long, { obj: 'name', val: name_puny }]
|
||||
],
|
||||
'2201' => [ # Authorisation error
|
||||
[:auth_info, :wrong_pw]
|
||||
[:transfer_code, :wrong_pw]
|
||||
],
|
||||
'2202' => [
|
||||
[:base, :invalid_auth_information_reserved]
|
||||
|
@ -182,7 +182,7 @@ class Epp::Domain < Domain
|
|||
# at[:domain_statuses_attributes] = domain_statuses_attrs(frame, action)
|
||||
|
||||
pw = frame.css('authInfo > pw').text
|
||||
at[:auth_info] = pw if pw.present?
|
||||
at[:transfer_code] = pw if pw.present?
|
||||
|
||||
if new_record?
|
||||
dnskey_frame = frame.css('extension create')
|
||||
|
@ -641,47 +641,6 @@ class Epp::Domain < Domain
|
|||
end
|
||||
end
|
||||
|
||||
# TODO: Eager load problems here. Investigate how it's possible not to query contact again
|
||||
# Check if versioning works with update_column
|
||||
def transfer_contacts(registrar_id)
|
||||
transfer_registrant(registrar_id)
|
||||
transfer_domain_contacts(registrar_id)
|
||||
end
|
||||
|
||||
def copy_and_transfer_contact(contact_id, registrar_id)
|
||||
c = Contact.find(contact_id) # n+1 workaround
|
||||
oc = c.deep_clone
|
||||
oc.code = nil
|
||||
oc.registrar_id = registrar_id
|
||||
oc.copy_from_id = c.id
|
||||
oc.generate_code
|
||||
oc.domain_transfer = true
|
||||
oc.remove_address unless Contact.address_processing?
|
||||
oc.save!(validate: false)
|
||||
oc
|
||||
end
|
||||
|
||||
def transfer_registrant(registrar_id)
|
||||
return if registrant.registrar_id == registrar_id
|
||||
self.registrant_id = copy_and_transfer_contact(registrant_id, registrar_id).id
|
||||
end
|
||||
|
||||
def transfer_domain_contacts(registrar_id)
|
||||
copied_ids = []
|
||||
contacts.each do |c|
|
||||
next if copied_ids.include?(c.id) || c.registrar_id == registrar_id
|
||||
|
||||
if registrant_id_was == c.id # registrant was copied previously, do not copy it again
|
||||
oc = OpenStruct.new(id: registrant_id)
|
||||
else
|
||||
oc = copy_and_transfer_contact(c.id, registrar_id)
|
||||
end
|
||||
|
||||
domain_contacts.where(contact_id: c.id).update_all({ contact_id: oc.id }) # n+1 workaround
|
||||
copied_ids << c.id
|
||||
end
|
||||
end
|
||||
|
||||
# rubocop: enable Metrics/PerceivedComplexity
|
||||
# rubocop: enable Metrics/CyclomaticComplexity
|
||||
# rubocop: disable Metrics/MethodLength
|
||||
|
@ -707,8 +666,8 @@ class Epp::Domain < Domain
|
|||
transaction do
|
||||
dt = domain_transfers.create!(
|
||||
transfer_requested_at: Time.zone.now,
|
||||
transfer_to: current_user.registrar,
|
||||
transfer_from: registrar
|
||||
old_registrar: registrar,
|
||||
new_registrar: current_user.registrar
|
||||
)
|
||||
|
||||
if dt.pending?
|
||||
|
@ -720,9 +679,9 @@ class Epp::Domain < Domain
|
|||
end
|
||||
|
||||
if dt.approved?
|
||||
transfer_contacts(current_user.registrar_id)
|
||||
transfer_contacts(current_user.registrar)
|
||||
dt.notify_losing_registrar(old_contact_codes, old_registrant_code)
|
||||
generate_auth_info!
|
||||
regenerate_transfer_code
|
||||
self.registrar = current_user.registrar
|
||||
end
|
||||
|
||||
|
@ -737,7 +696,7 @@ class Epp::Domain < Domain
|
|||
|
||||
def approve_transfer(frame, current_user)
|
||||
pt = pending_transfer
|
||||
if current_user.registrar != pt.transfer_from
|
||||
if current_user.registrar != pt.old_registrar
|
||||
throw :epp_error, {
|
||||
msg: I18n.t('transfer_can_be_approved_only_by_current_registrar'),
|
||||
code: '2304'
|
||||
|
@ -750,9 +709,9 @@ class Epp::Domain < Domain
|
|||
transferred_at: Time.zone.now
|
||||
)
|
||||
|
||||
transfer_contacts(pt.transfer_to_id)
|
||||
generate_auth_info
|
||||
self.registrar = pt.transfer_to
|
||||
transfer_contacts(pt.new_registrar)
|
||||
regenerate_transfer_code
|
||||
self.registrar = pt.new_registrar
|
||||
|
||||
attach_legal_document(self.class.parse_legal_document_from_frame(frame))
|
||||
save!(validate: false)
|
||||
|
@ -763,7 +722,7 @@ class Epp::Domain < Domain
|
|||
|
||||
def reject_transfer(frame, current_user)
|
||||
pt = pending_transfer
|
||||
if current_user.registrar != pt.transfer_from
|
||||
if current_user.registrar != pt.old_registrar
|
||||
throw :epp_error, {
|
||||
msg: I18n.t('transfer_can_be_rejected_only_by_current_registrar'),
|
||||
code: '2304'
|
||||
|
@ -872,7 +831,7 @@ class Epp::Domain < Domain
|
|||
|
||||
# For domain transfer
|
||||
def authenticate(pw)
|
||||
errors.add(:auth_info, :wrong_pw) if pw != auth_info
|
||||
errors.add(:transfer_code, :wrong_pw) if pw != transfer_code
|
||||
errors.empty?
|
||||
end
|
||||
|
||||
|
|
|
@ -140,8 +140,8 @@ class Registrar < ActiveRecord::Base
|
|||
def domain_transfers
|
||||
at = DomainTransfer.arel_table
|
||||
DomainTransfer.where(
|
||||
at[:transfer_to_id].eq(id).or(
|
||||
at[:transfer_from_id].eq(id)
|
||||
at[:new_registrar_id].eq(id).or(
|
||||
at[:old_registrar_id].eq(id)
|
||||
)
|
||||
)
|
||||
end
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
class DomainTransferVersion < PaperTrail::Version
|
||||
include VersionSession
|
||||
self.table_name = :log_domain_transfers
|
||||
self.sequence_name = :log_domain_transfers_id_seq
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue