Domain creating refactor

This commit is contained in:
Martin Lensment 2014-08-11 16:41:31 +03:00
parent a01f03a6d5
commit b26345dde4
8 changed files with 103 additions and 86 deletions

View file

@ -35,11 +35,16 @@ module Epp::Common
def handle_errors(obj=nil) def handle_errors(obj=nil)
if obj if obj
obj.construct_epp_errors obj.construct_epp_errors
@errors = obj.errors[:epp_errors] @errors += obj.errors[:epp_errors]
end end
render '/epp/error' render '/epp/error'
end end
def append_errors(obj)
obj.construct_epp_errors
@errors += obj.errors[:epp_errors]
end
def xml_attrs_present?(ph, attributes) def xml_attrs_present?(ph, attributes)
attributes.each do |x| attributes.each do |x|
epp_errors << {code: '2003', msg: I18n.t('errors.messages.required_parameter_missing', key: x.last)} unless has_attribute(ph, x) epp_errors << {code: '2003', msg: I18n.t('errors.messages.required_parameter_missing', key: x.last)} unless has_attribute(ph, x)

View file

@ -1,27 +1,12 @@
module Epp::DomainsHelper module Epp::DomainsHelper
def create_domain def create_domain
ph = params_hash['epp']['command']['create']['create']
unless xml_attrs_present?(ph, [['name'], ['ns'], ['authInfo'], ['contact'], ['registrant']])
render '/epp/error' and return
end
@domain = Domain.new(domain_create_params(ph))
if owner_contact_id = Contact.find_by(code: ph[:registrant]).try(:id)
@domain.owner_contact_id = owner_contact_id
else
epp_errors << {code: '2303', msg: I18n.t('errors.messages.epp_registrant_not_found'), value: {obj: 'registrant', val: ph[:registrant]}}
render '/epp/error' and return
end
Domain.transaction do Domain.transaction do
if @domain.save && @domain.attach_contacts(domain_contacts) && @domain.attach_nameservers(domain_nameservers) @domain = Domain.new(domain_create_params)
render '/epp/domains/create'
else handle_errors(@domain) and return unless @domain.attach_objects(@ph, params[:frame])
handle_errors(@domain) handle_errors(@domain) and return unless @domain.save
raise ActiveRecord::Rollback
end render '/epp/domains/create'
end end
end end
@ -44,11 +29,31 @@ module Epp::DomainsHelper
### HELPER METHODS ### ### HELPER METHODS ###
private private
## CREATE
def validate_domain_create_request
@ph = params_hash['epp']['command']['create']['create']
xml_attrs_present?(@ph, [['name'], ['ns'], ['authInfo'], ['contact'], ['registrant']])
end
def domain_create_params
{
name: @ph[:name],
registrar_id: current_epp_user.registrar.try(:id),
registered_at: Time.now,
period: @ph[:period].to_i,
valid_from: Date.today,
valid_to: Date.today + @ph[:period].to_i.years,
auth_info: @ph[:authInfo][:pw]
}
end
## RENEW
def validate_domain_renew_request def validate_domain_renew_request
@ph = params_hash['epp']['command']['renew']['renew'] @ph = params_hash['epp']['command']['renew']['renew']
xml_attrs_present?(@ph, [['name'], ['curExpDate'], ['period']]) xml_attrs_present?(@ph, [['name'], ['curExpDate'], ['period']])
end end
## SHARED
def find_domain def find_domain
domain = Domain.find_by(name: @ph[:name]) domain = Domain.find_by(name: @ph[:name])
unless domain unless domain
@ -56,38 +61,4 @@ module Epp::DomainsHelper
end end
domain domain
end end
def domain_create_params(ph)
{
name: ph[:name],
registrar_id: current_epp_user.registrar.try(:id),
registered_at: Time.now,
period: ph[:period].to_i,
valid_from: Date.today,
valid_to: Date.today + ph[:period].to_i.years,
auth_info: ph[:authInfo][:pw]
}
end
def domain_contacts
parsed_frame = Nokogiri::XML(params[:frame]).remove_namespaces!
res = {}
Contact::CONTACT_TYPES.each do |ct|
res[ct.to_sym] ||= []
parsed_frame.css("contact[type='#{ct}']").each do |x|
res[ct.to_sym] << Hash.from_xml(x.to_s).with_indifferent_access
end
end
res
end
def domain_nameservers
ph = params_hash['epp']['command']['create']['create']['ns']
return [] unless ph
return ph[:hostObj] if ph[:hostObj]
return ph[:hostAttr] if ph[:hostAttr]
[]
end
end end

View file

@ -34,9 +34,13 @@ class Domain < ActiveRecord::Base
validates :name_dirty, domain_name: true, uniqueness: true validates :name_dirty, domain_name: true, uniqueness: true
validates :period, numericality: { only_integer: true, greater_than: 0, less_than: 100 } validates :period, numericality: { only_integer: true, greater_than: 0, less_than: 100 }
validates :name, :owner_contact, presence: true validates :name, :owner_contact, presence: true
validate :validate_period
validates_associated :nameservers validates_associated :nameservers
validate :validate_period
validate :validate_nameservers_count
validate :validate_admin_contacts_count
def name=(value) def name=(value)
value.strip! value.strip!
write_attribute(:name, SimpleIDN.to_unicode(value)) write_attribute(:name, SimpleIDN.to_unicode(value))
@ -44,18 +48,37 @@ class Domain < ActiveRecord::Base
write_attribute(:name_dirty, value) write_attribute(:name_dirty, value)
end end
def attach_objects(ph, frame)
attach_owner_contact(ph[:registrant])
attach_contacts(self.class.parse_contacts_from_frame(frame))
attach_nameservers(self.class.parse_nameservers_from_params(ph[:ns]))
errors.empty?
end
def attach_owner_contact(code)
self.owner_contact = Contact.find_by(code: code)
errors.add(:owner_contact, {
obj: 'registrant',
val: code,
msg: I18n.t('errors.messages.epp_registrant_not_found')
}) unless owner_contact
end
def attach_contacts(contacts) def attach_contacts(contacts)
contacts.each do |k, v| contacts.each do |k, v|
v.each do |x| v.each do |x|
contact = Contact.find_by(code: x[:contact]) if contact = Contact.find_by(code: x[:contact])
attach_contact(k, contact) and next if contact attach_contact(k, contact)
else
# Detailed error message with value to display in EPP response # Detailed error message with value to display in EPP response
errors.add(:domain_contacts, { errors.add(:domain_contacts, {
obj: 'contact', obj: 'contact',
val: x[:contact], val: x[:contact],
msg: errors.generate_message(:domain_contacts, :not_found) msg: errors.generate_message(:domain_contacts, :not_found)
}) })
end
end end
end end
@ -64,29 +87,17 @@ class Domain < ActiveRecord::Base
if owner_contact.citizen? if owner_contact.citizen?
attach_contact(Contact::CONTACT_TYPE_ADMIN, owner_contact) if admin_contacts.empty? attach_contact(Contact::CONTACT_TYPE_ADMIN, owner_contact) if admin_contacts.empty?
end end
validate_admin_contacts_count
errors.empty?
end end
def attach_contact(type, contact) def attach_contact(type, contact)
domain_contacts.create( tech_contacts << contact if type.to_sym == :tech
contact: contact, admin_contacts << contact if type.to_sym == :admin
contact_type: type
)
end end
def attach_nameservers(ns_list) def attach_nameservers(ns_list)
ns_list.each do |ns| ns_list.each do |ns|
attach_nameserver(ns) attach_nameserver(ns)
end end
save
validate_nameservers_count
errors.empty?
end end
def attach_nameserver(ns) def attach_nameserver(ns)
@ -107,12 +118,12 @@ class Domain < ActiveRecord::Base
self.nameservers.build(attrs) self.nameservers.build(attrs)
end end
### VALIDATIONS ###
def validate_nameservers_count def validate_nameservers_count
unless nameservers.count.between?(1, 13) unless nameservers.length.between?(1, 13)
errors.add(:nameservers, :out_of_range, {min: 1, max: 13}) errors.add(:nameservers, :out_of_range, {min: 1, max: 13})
end end
errors.empty?
end end
def validate_admin_contacts_count def validate_admin_contacts_count
@ -156,6 +167,27 @@ class Domain < ActiveRecord::Base
end end
class << self class << self
def parse_contacts_from_frame(frame)
parsed_frame = Nokogiri::XML(frame).remove_namespaces!
res = {}
Contact::CONTACT_TYPES.each do |ct|
res[ct.to_sym] ||= []
parsed_frame.css("contact[type='#{ct}']").each do |x|
res[ct.to_sym] << Hash.from_xml(x.to_s).with_indifferent_access
end
end
res
end
def parse_nameservers_from_params(ph)
return [] unless ph
return ph[:hostObj] if ph[:hostObj]
return ph[:hostAttr] if ph[:hostAttr]
[]
end
def check_availability(domains) def check_availability(domains)
domains = [domains] if domains.is_a?(String) domains = [domains] if domains.is_a?(String)

View file

@ -1,4 +1,6 @@
class DomainContact < ActiveRecord::Base class DomainContact < ActiveRecord::Base
belongs_to :contact belongs_to :contact
belongs_to :domain belongs_to :domain
scope :tech, -> {where(contact_type: :tech)}
end end

View file

@ -2,8 +2,8 @@ Fabricator(:contact) do
name Faker::Name.name name Faker::Name.name
phone '+372.12345678' phone '+372.12345678'
email Faker::Internet.email email Faker::Internet.email
ident '37605030299' ident '37605030299'
code "sh#{Faker::Number.number(4)}" code { "sh#{Faker::Number.number(4)}" }
ident_type 'op' ident_type 'op'
address address
end end

View file

@ -4,4 +4,6 @@ Fabricator(:domain) do
period 1 period 1
period_unit 'y' period_unit 'y'
owner_contact(fabricator: :contact) owner_contact(fabricator: :contact)
nameservers(count: 3)
admin_contacts(count: 1) { Fabricate(:contact) }
end end

View file

@ -0,0 +1,3 @@
Fabricator(:nameserver) do
hostname { "ns.#{Faker::Internet.domain_word}.ee" }
end

View file

@ -41,7 +41,9 @@ describe Domain do
expect(d.errors.messages).to match_array({ expect(d.errors.messages).to match_array({
name: ['is missing'], name: ['is missing'],
period: ['is not a number'], period: ['is not a number'],
owner_contact: ["Registrant is missing"] owner_contact: ["Registrant is missing"],
admin_contacts: ["Admin contact is missing"],
nameservers: ["Nameservers count must be between 1-13"]
}) })
end end