Removed and updated additional files

This commit is contained in:
Sergei Tsõganov 2022-10-13 14:06:33 +03:00
parent 11c2af075a
commit 04b55068df
29 changed files with 154 additions and 1534 deletions

View file

@ -32,9 +32,7 @@ class Ability
def epp # Registrar/api_user dynamic role
if @user.registrar.api_ip_white?(@ip)
can :manage, Depp::Contact
can :manage, :xml_console
can :manage, Depp::Domain
end
can :manage, Account
@ -122,7 +120,6 @@ class Ability
customer_service
can :manage, :registrant_domains
can :manage, :registrant_whois
can :manage, Depp::Domain
can :manage, Domain
end

View file

@ -1,318 +0,0 @@
module Depp
class Contact
include ActiveModel::Model
attr_accessor :id, :name, :email, :phone, :org_name,
:ident, :ident_type, :ident_country_code,
:street, :city, :zip, :state, :country_code,
:password, :legal_document, :statuses, :code,
:email_history
DISABLED = 'Disabled'
DISCLOSURE_TYPES = [DISABLED, '1', '0']
TYPES = %w( org priv birthday )
SELECTION_TYPES = [
['Business code', 'org'],
['Personal identification code', 'priv'],
['Birthday', 'birthday']
]
validates :phone, e164: true, phone: true
class << self
attr_reader :epp_xml, :user
def new_from_params(params)
new(
id: params[:code],
code: params[:code],
email: params[:email],
phone: params[:phone],
ident: params[:ident],
ident_type: params[:ident_type],
ident_country_code: params[:ident_country_code],
# postalInfo
name: params[:name],
org_name: params[:org_name],
# address
street: params[:street],
city: params[:city],
zip: params[:zip],
state: params[:state],
country_code: params[:country_code]
)
end
def find_by_id(id)
data = info_xml(id)
res = data.css('epp response resData infData')
ext = data.css('epp response extension')
new(
id: res.css('id').text,
code: res.css('id').text,
email: res.css('email').text,
phone: res.css('voice').text,
ident: ext.css('ident').text,
ident_type: ext.css('ident').first.try(:attributes).try(:[], 'type').try(:value),
ident_country_code: ext.css('ident').first.try(:attributes).try(:[], 'cc').try(:value),
# postalInfo
name: res.css('postalInfo name').text,
org_name: res.css('postalInfo org').text,
# address
street: res.css('postalInfo addr street').text,
city: res.css('postalInfo addr city').text,
zip: res.css('postalInfo addr pc').text,
state: res.css('postalInfo addr sp').text,
country_code: res.css('postalInfo addr cc').text,
# authInfo
password: res.css('authInfo pw').text,
# statuses
statuses: data.css('status').map { |s| [s['s'], s.text] }
)
end
def user=(user)
@user = user
@epp_xml = EppXml::Contact.new(cl_trid_prefix: user.tag, schema_prefix: 'contact-ee',
schema_version: '1.1')
end
def info_xml(id, password = nil)
xml = epp_xml.info(
id: { value: id },
authInfo: { pw: { value: password } }
)
user.request(xml)
end
def construct_check_hash_from_data(data)
res = data.css('epp response resData chkData cd')
@contacts = []
res.each do |_r|
id = res.css('id').try(:text)
reason = res.css('reason').present? ? res.css('reason').text : I18n.t(:available)
@contacts << { id: id, reason: reason }
end
@contacts
end
def contact_id_from_xml(data)
id = data.css('epp response resData creData id').text
id.blank? ? nil : id
end
def construct_create_disclosure_xml(cph, flag)
xml = { disclose: {} }
cph.each do |k, v|
xml[:disclose][k] = {}
xml[:disclose][k][:value] = v
end
xml[:disclose][:attrs] = {}
xml[:disclose][:attrs][:flag] = flag
xml.with_indifferent_access
end
# cpd = contact_params[:disclose]
def extract_disclosure_hash(cpd)
return {} unless cpd
cpd.delete_if { |k, v| v if v != '1' && k == 'flag' }
end
def extract_info_disclosure(data)
hash = {}
data.css('disclose').each do |d|
flag = d.attributes['flag'].value
next unless flag
hash[flag] = {}
d.children.each do |c|
hash[flag][c.name] = flag if %w( name email fax voice addr org_name ).include?(c.name)
end
end
hash
end
def type_string(type_code)
return '' if type_code.blank?
t = SELECTION_TYPES.select { |tp| tp.second == type_code }
t.try(:first).try(:first)
end
end
def save
return false unless valid?
hash = {
id: { value: code },
postalInfo: {
name: { value: name },
org: { value: org_name },
},
voice: { value: phone },
email: { value: email }
}
if ::Contact.address_processing?
hash[:postalInfo][:addr] = {
street: { value: street },
city: { value: city },
sp: { value: state },
pc: { value: zip },
cc: { value: country_code },
}
end
hash[:id] = nil if code.blank?
create_xml = Depp::Contact.epp_xml.create(hash, extension_xml(:create))
data = Depp::Contact.user.request(create_xml)
self.id = data.css('id').text
handle_errors(data)
end
# rubocop:disable Metrics/MethodLength
def update_attributes(params)
return false unless valid?
self.ident_country_code = params[:ident_country_code]
self.ident_type = params[:ident_type]
self.ident = params[:ident]
self.name = params[:name]
self.email = params[:email]
self.phone = params[:phone]
self.org_name = params[:org_name]
if ::Contact.address_processing?
self.street = params[:street]
self.city = params[:city]
self.zip = params[:zip]
self.state = params[:state]
self.country_code = params[:country_code]
end
attributes = {
id: { value: id },
chg: {
postalInfo: {
name: { value: name },
org: { value: org_name },
},
voice: { value: phone },
email: { value: email },
authInfo: {
pw: { value: password }
}
}
}
if ::Contact.address_processing?
attributes[:chg][:postalInfo][:addr] = {
street: { value: street },
city: { value: city },
sp: { value: state },
pc: { value: zip },
cc: { value: country_code }
}
end
update_xml = Depp::Contact.epp_xml.update(attributes, extension_xml(:update))
data = Depp::Contact.user.request(update_xml)
handle_errors(data)
end
# rubocop:enable Metrics/MethodLength
def delete
delete_xml = Contact.epp_xml.delete(
{
id: { value: id },
authInfo: { pw: { value: password } }
},
extension_xml(:delete)
)
data = Depp::Contact.user.request(delete_xml)
handle_errors(data)
end
def extension_xml(action)
xml = { _anonymus: [] }
case action
when :create
ident = ident_xml[:_anonymus].try(:first)
when :update
# detect if any ident has changed, nb! ident and self.ident is not always same
unless ident == self.ident && ident == ident_type && ident_country_code == self.ident_country_code
ident = ident_xml[:_anonymus].try(:first)
end
end
legal = legal_document_xml[:_anonymus].try(:first)
xml[:_anonymus] << ident if ident.present?
xml[:_anonymus] << legal if legal.present?
xml
end
def ident_xml
{
_anonymus: [
ident: { value: ident, attrs: { type: ident_type, cc: ident_country_code } }
]
}
end
def legal_document_xml
return {} if legal_document.blank?
type = legal_document.original_filename.split('.').last.downcase
{
_anonymus: [
legalDocument: { value: Base64.encode64(legal_document.read), attrs: { type: type } }
]
}
end
def check(id)
xml = epp_xml.check(id: { value: id })
current_user.request(xml)
end
def country_name
Country.new(country_code) || 'No access'
end
def org?
ident_type == 'org'
end
def priv?
ident_type == 'priv'
end
def persisted?
id.present?
end
def handle_errors(data)
data.css('result').each do |x|
success_codes = %(1000, 1300, 1301)
next if success_codes.include?(x['code'])
message = "#{x.css('msg').text} #{x.css('value').text}"
attr = message.split('[').last.strip.sub(']', '') if message.include?('[')
attr = :base if attr.nil?
attr = 'phone' if attr == 'voice'
attr = 'zip' if attr == 'pc'
errors.add(attr, message)
end
errors.blank?
end
end
end

View file

@ -1,26 +0,0 @@
module Depp
class Dnskey
FLAGS = [
['0 - not for DNSSEC validation', 0],
['256 - ZSK', 256],
['257 - KSK', 257]
]
ALGORITHMS = [
['3 - DSA/SHA-1', 3],
['5 - RSA/SHA-1', 5],
['6 - DSA-NSEC3-SHA1', 6],
['7 - RSASHA1-NSEC3-SHA1', 7],
['8 - RSA/SHA-256', 8],
['10 - RSA/SHA-512', 10],
['13 - ECDSA Curve P-256 with SHA-256', 13],
['14 - ECDSA Curve P-384 with SHA-384', 14],
['15 - Ed25519', 15],
['16 - Ed448', 16],
].freeze
PROTOCOLS = [3]
DS_DIGEST_TYPES = [1, 2]
end
end

View file

@ -1,351 +0,0 @@
module Depp
class Domain
include ActiveModel::Conversion
include RemoveHold
extend ActiveModel::Naming
attr_accessor :name, :current_user, :epp_xml
STATUSES = %w[
clientDeleteProhibited
clientHold
clientRenewProhibited
clientTransferProhibited
clientUpdateProhibited
].freeze
PERIODS = [
['3 months', '3m'],
['6 months', '6m'],
['9 months', '9m'],
['1 year', '1y'],
['2 years', '2y'],
['3 years', '3y'],
['4 years', '4y'],
['5 years', '5y'],
['6 years', '6y'],
['7 years', '7y'],
['8 years', '8y'],
['9 years', '9y'],
['10 years', '10y'],
].freeze
def initialize(args = {})
self.current_user = args[:current_user]
self.epp_xml = EppXml::Domain.new(
cl_trid_prefix: current_user.tag,
schema_prefix: 'domain-ee',
schema_version: '1.1'
)
end
def info(domain_name)
xml = epp_xml.info(name: { value: domain_name })
current_user.request(xml)
end
def check(domain_name)
xml = epp_xml.check(
_anonymus: [
name: { value: domain_name }
]
)
current_user.request(xml)
end
def create(domain_params)
dns_hash = {}
keys = Domain.create_dnskeys_hash(domain_params)
dns_hash[:_anonymus] = keys if keys.any?
period = domain_params[:period].to_i.to_s
period_unit = domain_params[:period][-1].to_s
xml = if domain_params[:nameservers_attributes]
.select { |_key, value| value['hostname'].present? }.any?
epp_xml.create({
name: { value: domain_params[:name] },
period: { value: period, attrs: { unit: period_unit } },
ns: Domain.create_nameservers_hash(domain_params),
registrant: { value: domain_params[:registrant] },
_anonymus: Domain.create_contacts_hash(domain_params)
}, dns_hash, Domain.construct_custom_params_hash(domain_params))
else
epp_xml.create({
name: { value: domain_params[:name] },
period: { value: period, attrs: { unit: period_unit } },
registrant: { value: domain_params[:registrant] },
_anonymus: Domain.create_contacts_hash(domain_params)
}, dns_hash, Domain.construct_custom_params_hash(domain_params))
end
current_user.request(xml)
end
def update(domain_params)
data = current_user.request(epp_xml.info(name: { value: domain_params[:name] }))
old_domain_params = Depp::Domain.construct_params_from_server_data(data)
xml = epp_xml.update(
Depp::Domain.construct_edit_hash(domain_params, old_domain_params),
Depp::Domain.construct_ext_edit_hash(domain_params, old_domain_params),
Depp::Domain.construct_custom_params_hash(domain_params)
)
current_user.request(xml)
end
def delete(domain_params)
xml = epp_xml.delete({
name: { value: domain_params[:name] },
},
Depp::Domain.construct_custom_params_hash(domain_params),
(domain_params[:verified].present? && 'yes'))
current_user.request(xml)
end
def renew(params)
period = params[:period].to_i.to_s
period_unit = params[:period][-1].to_s
current_user.request(epp_xml.renew(name: { value: params[:domain_name] },
curExpDate: { value: params[:cur_exp_date] },
period: { value: period, attrs: { unit: period_unit } }))
end
def transfer(params)
op = params[:request] ? 'request' : nil
op = params[:query] ? 'query' : op
op = params[:approve] ? 'approve' : op
op = params[:reject] ? 'reject' : op
current_user.request(epp_xml.transfer({
name: { value: params[:domain_name] },
authInfo: { pw: { value: params[:transfer_code] } }
}, op, Domain.construct_custom_params_hash(params)))
end
def confirm_transfer(domain_params)
data = current_user.request(epp_xml.info(name: { value: domain_params[:name] }))
pw = data.css('pw').text
xml = epp_xml.transfer({
name: { value: domain_params[:name] },
authInfo: { pw: { value: pw } }
}, 'approve')
current_user.request(xml)
end
class << self
def default_period
'1y'
end
def default_params
ret = {}
ret[:contacts_attributes] ||= {}
ENV['default_admin_contacts_count'].to_i.times do |i|
ret[:contacts_attributes][i] = { code: '', type: 'admin' }
end
ret[:nameservers_attributes] ||= {}
ENV['default_nameservers_count'].to_i.times do |i|
ret[:nameservers_attributes][i] = {}
end
ret[:dnskeys_attributes] ||= { 0 => {} }
ret[:statuses_attributes] ||= { 0 => {} }
ret.with_indifferent_access
end
def construct_params_from_server_data(data)
ret = default_params
ret[:name] = data.css('name').text
ret[:registrant] = data.css('registrant').text
data.css('contact').each_with_index do |x, i|
ret[:contacts_attributes][i] = { code: x.text, type: x['type'] }
end
data.css('hostAttr').each_with_index do |x, i|
ret[:nameservers_attributes][i] = {
hostname: x.css('hostName').text,
ipv4: Array(x.css('hostAddr[ip="v4"]')).map(&:text).join(','),
ipv6: Array(x.css('hostAddr[ip="v6"]')).map(&:text).join(',')
}
end
data.css('keyData').each_with_index do |x, i|
ret[:dnskeys_attributes][i] = {
flags: x.css('flags').text,
protocol: x.css('protocol').text,
alg: x.css('alg').text,
public_key: x.css('pubKey').text,
ds_key_tag: x.css('keyTag').first.try(:text),
ds_alg: x.css('alg').first.try(:text),
ds_digest_type: x.css('digestType').first.try(:text),
ds_digest: x.css('digest').first.try(:text)
}
end
data.css('status').each_with_index do |x, i|
next unless STATUSES.include?(x['s'])
ret[:statuses_attributes][i] = {
code: x['s'],
description: x.text
}
end
ret
end
def construct_custom_params_hash(domain_params)
custom_params = { _anonymus: [] }
if domain_params[:legal_document].present?
type = domain_params[:legal_document].original_filename.split('.').last.downcase
custom_params[:_anonymus] << {
legalDocument: { value: Base64.encode64(domain_params[:legal_document].read), attrs: { type: type } }
}
end
if domain_params[:reserved_pw].present?
custom_params[:_anonymus] << { reserved: { pw: { value: domain_params[:reserved_pw] } } }
end
custom_params
end
def construct_edit_hash(domain_params, old_domain_params)
contacts = array_difference(create_contacts_hash(domain_params), create_contacts_hash(old_domain_params))
add_anon = contacts
contacts = array_difference(create_contacts_hash(old_domain_params), create_contacts_hash(domain_params))
rem_anon = contacts
add_arr = []
add_ns = create_nameservers_hash(domain_params) - create_nameservers_hash(old_domain_params)
add_arr << { ns: add_ns } if add_ns.any?
add_arr << { _anonymus: add_anon } if add_anon.any?
rem_arr = []
rem_ns = create_nameservers_hash(old_domain_params) - create_nameservers_hash(domain_params)
rem_arr << { ns: rem_ns } if rem_ns.any?
rem_arr << { _anonymus: rem_anon } if rem_anon.any?
if domain_params[:registrant] != old_domain_params[:registrant]
chg = [{ registrant: { value: domain_params[:registrant] } }] unless domain_params[:verified].present?
if domain_params[:verified]
chg = [{ registrant: { value: domain_params[:registrant], attrs: { verified: 'yes' } } }]
end
end
add_arr = nil if add_arr.none?
rem_arr = nil if rem_arr.none?
{
name: { value: domain_params[:name] },
add: add_arr,
rem: rem_arr,
chg: chg
}
end
def construct_ext_edit_hash(domain_params, old_domain_params)
rem_keys = create_dnskeys_hash(old_domain_params) - create_dnskeys_hash(domain_params)
add_keys = create_dnskeys_hash(domain_params) - create_dnskeys_hash(old_domain_params)
hash = {}
hash[:rem] = rem_keys if rem_keys.any?
hash[:add] = add_keys if add_keys.any?
hash
end
def create_nameservers_hash(domain_params)
ret = []
domain_params[:nameservers_attributes].each do |_k, v|
next if v['hostname'].blank?
host_attr = []
host_attr << { hostName: { value: v['hostname'] } }
if v['ipv4'].present?
v['ipv4'].to_s.split(',').each do |ip|
host_attr << { hostAddr: { value: ip, attrs: { ip: 'v4' } } }
end
end
if v['ipv6'].present?
v['ipv6'].to_s.split(',').each do |ip|
host_attr << { hostAddr: { value: ip, attrs: { ip: 'v6' } } }
end
end
ret << { hostAttr: host_attr }
end
ret
end
def create_contacts_hash(domain_params)
ret = []
domain_params[:contacts_attributes].each do |_k, v|
next if v['code'].blank?
ret << {
contact: { value: v['code'], attrs: { type: v['type'] } }
}
end
ret
end
def create_dnskeys_hash(domain_params)
ret = []
domain_params[:dnskeys_attributes].each do |_k, v|
if v['ds_key_tag'].blank?
kd = create_key_data_hash(v)
if kd
ret << {
keyData: kd
}
end
else
ret << {
dsData: [
keyTag: { value: v['ds_key_tag'] },
alg: { value: v['ds_alg'] },
digestType: { value: v['ds_digest_type'] },
digest: { value: v['ds_digest'] },
keyData: create_key_data_hash(v)
]
}
end
end
ret
end
def create_key_data_hash(key_data_params)
return nil if key_data_params['public_key'].blank?
{
flags: { value: key_data_params['flags'] },
protocol: { value: key_data_params['protocol'] },
alg: { value: key_data_params['alg'] },
pubKey: { value: key_data_params['public_key'] }
}
end
def array_difference(x, y)
ret = x.dup
y.each do |element|
index = ret.index(element)
ret.delete_at(index) if index
end
ret
end
end
end
end

View file

@ -1,66 +0,0 @@
module Depp
class User
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :tag, :password, :pki
validates :tag, :password, presence: true
validate :validate_existance_in_server
def initialize(args = {})
args.each { |k, v| send("#{k}=", v) }
end
def server
client_cert = File.read(ENV['cert_path'])
client_key = File.read(ENV['key_path'])
port = ENV['epp_port'] || '700'
@server_cache ||= Epp::Server.new({
server: ENV['epp_hostname'],
tag: tag,
password: password,
port: port,
cert: OpenSSL::X509::Certificate.new(client_cert),
key: OpenSSL::PKey::RSA.new(client_key)
})
end
def request(xml)
Nokogiri::XML(server.request(xml)).remove_namespaces!
rescue EppErrorResponse => e
Nokogiri::XML(e.response_xml.to_s).remove_namespaces!
end
private
def validate_existance_in_server
return if errors.any?
res = server.open_connection
unless Nokogiri::XML(res).css('greeting')
errors.add(:base, :failed_to_open_connection_to_epp_server)
server.close_connection # just in case
return
end
ex = EppXml::Session.new(cl_trid_prefix: tag)
xml = ex.login(clID: { value: tag }, pw: { value: password })
res = server.send_request(xml)
if Nokogiri::XML(res).css('result').first['code'] != '1000'
errors.add(:base, Nokogiri::XML(res).css('result').text)
end
server.close_connection
rescue OpenSSL::SSL::SSLError => e
Rails.logger.error "INVALID CERT: #{e}"
Rails.logger.error "INVALID CERT DEBUG INFO: epp_hostname: #{ENV['epp_hostname']}," \
"port: #{ENV['epp_port']}, cert_path: #{ENV['cert_path']}, key_path: #{ENV['key_path']}"
errors.add(:base, :invalid_cert)
end
end
end

View file

@ -25,10 +25,10 @@ class Dnskey < ApplicationRecord
}
# IANA numbers, single authority list
ALGORITHMS = Depp::Dnskey::ALGORITHMS.map {|pair| pair[1].to_s}.freeze
PROTOCOLS = %w(3)
FLAGS = %w(0 256 257) # 256 = ZSK, 257 = KSK
DS_DIGEST_TYPE = [1,2]
ALGORITHMS = %w[3 5 6 7 8 10 13 14 15 16].freeze
PROTOCOLS = %w[3].freeze
FLAGS = %w[0 256 257].freeze # 256 = ZSK, 257 = KSK
DS_DIGEST_TYPE = [1, 2].freeze
RESOLVERS = ENV['dnssec_resolver_ips'].to_s.strip.split(', ').freeze
self.ignored_columns = %w[legacy_domain_id]

View file

@ -13,6 +13,22 @@ class Domain < ApplicationRecord
include Domain::Disputable
include Domain::BulkUpdatable
PERIODS = [
['3 months', '3m'],
['6 months', '6m'],
['9 months', '9m'],
['1 year', '1y'],
['2 years', '2y'],
['3 years', '3y'],
['4 years', '4y'],
['5 years', '5y'],
['6 years', '6y'],
['7 years', '7y'],
['8 years', '8y'],
['9 years', '9y'],
['10 years', '10y'],
].freeze
attr_accessor :roles,
:legal_document_id,
:is_admin,