Merge branch 'master' of github.com:internetee/registry

This commit is contained in:
Martin Lensment 2014-11-12 19:05:42 +02:00
commit 38dc1c548b
45 changed files with 590 additions and 401 deletions

View file

@ -70,6 +70,15 @@ gem 'therubyracer', platforms: :ruby
# for settings
gem 'rails-settings-cached', '0.4.1'
# for scp to whois server
gem 'net-ssh'
gem 'net-scp'
# delayed job
gem 'delayed_job_active_record', '~> 4.0.2'
# to process delayed jobs
gem 'daemons'
group :development, :test do
gem 'capybara', '~> 2.4.1'
# For feature testing

View file

@ -78,8 +78,14 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.8.0)
daemons (1.1.9)
database_cleaner (1.3.0)
debug_inspector (0.0.2)
delayed_job (4.0.4)
activesupport (>= 3.0, < 4.2)
delayed_job_active_record (4.0.2)
activerecord (>= 3.0, < 4.2)
delayed_job (>= 3.0, < 4.1)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
devise (3.3.0)
@ -163,6 +169,9 @@ GEM
mini_portile (0.6.0)
minitest (5.4.2)
multi_json (1.10.1)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
net-ssh (2.9.1)
nokogiri (1.6.2.1)
mini_portile (= 0.6.0)
nprogress-rails (0.1.3.1)
@ -359,7 +368,9 @@ DEPENDENCIES
cancan (~> 1.6.10)
capybara (~> 2.4.1)
coffee-rails (~> 4.0.0)
daemons
database_cleaner (~> 1.3.0)
delayed_job_active_record (~> 4.0.2)
devise (~> 3.3.0)
epp (~> 1.4.0)
epp-xml (~> 0.7.0)
@ -373,6 +384,8 @@ DEPENDENCIES
jbuilder (~> 2.0)
jquery-rails
kaminari (~> 0.16.1)
net-scp
net-ssh
nokogiri (~> 1.6.2.1)
nprogress-rails (~> 0.1.3.1)
paper_trail (~> 3.0.5)

View file

@ -1,3 +1,7 @@
.error-tab > a {
color: #a94442 !important;
}
.edit-highlight {
background-color: #E7E7E7;
}

View file

@ -1,6 +0,0 @@
class Admin::ContactHistoriesController < AdminController
def index
@q = ContactVersion.deleted.search(params[:q])
@contacts = @q.result.page(params[:page])
end
end

View file

@ -1,18 +0,0 @@
class Admin::ContactVersionsController < AdminController
before_action :set_contact, only: [:show]
def index
@q = Contact.search(params[:q])
@contacts = @q.result.page(params[:page])
end
def show
@versions = @contact.versions
end
private
def set_contact
@contact = Contact.find(params[:id])
end
end

View file

@ -0,0 +1,5 @@
class Admin::DelayedJobsController < AdminController
def index
@jobs = Delayed::Job.all
end
end

View file

@ -1,6 +0,0 @@
class Admin::DomainHistoriesController < AdminController
def index
@q = DomainVersion.deleted.search(params[:q])
@domains = @q.result.page(params[:page])
end
end

View file

@ -1,18 +1,11 @@
class Admin::DomainVersionsController < AdminController
before_action :set_domain, only: [:show]
def index
@q = Domain.search(params[:q])
@q = DomainVersion.deleted.search(params[:q])
@domains = @q.result.page(params[:page])
end
def show
@versions = @domain.versions
end
private
def set_domain
@domain = Domain.find(params[:id])
@versions = DomainVersion.where(item_id: params[:id])
@name = @versions.last.name
end
end

View file

@ -1,10 +1,8 @@
module Epp::ContactsHelper
def create_contact
@contact = Contact.new(contact_and_address_attributes)
@contact.generate_code
@contact.registrar = current_epp_user.registrar
render '/epp/contacts/create' and return if stamp(@contact) && @contact.save
handle_errors(@contact)
end
@ -16,7 +14,7 @@ module Epp::ContactsHelper
render 'epp/contacts/update'
else
contact_exists?(code)
handle_errors(@contact)
handle_errors(@contact) and return
end
end
@ -38,7 +36,7 @@ module Epp::ContactsHelper
end
def info_contact
handle_errors and return unless rights?
# handle_errors and return unless rights?
@contact = find_contact
handle_errors(@contact) and return unless @contact
render 'epp/contacts/info'
@ -56,7 +54,7 @@ module Epp::ContactsHelper
## CREATE
def validate_contact_create_request
@ph = params_hash['epp']['command']['create']['create']
xml_attrs_present?(@ph, [%w(authInfo pw), %w(postalInfo)])
xml_attrs_present?(@ph, [%w(postalInfo)])
return epp_errors.empty? unless @ph['postalInfo'].is_a?(Hash) || @ph['postalInfo'].is_a?(Array)

View file

@ -17,18 +17,18 @@ class Address < ActiveRecord::Base
# errors, used = [], []
# parsed_frame.css('postalInfo').each do |pi|
# attr = pi.attributes['type'].try(:value)
# errors << {
# code: 2003, msg: I18n.t('errors.messages.attr_missing', key: 'type')
# errors << {
# code: 2003, msg: I18n.t('errors.messages.attr_missing', key: 'type')
# } and next unless attr
# unless TYPES.include?(attr)
# errors << {
# code: 2005,
# msg: I18n.t('errors.messages.invalid_type'), value: { obj: 'type', val: attr }
# errors << {
# code: 2005,
# msg: I18n.t('errors.messages.invalid_type'), value: { obj: 'type', val: attr }
# }
# next
# end
# errors << {
# code: 2005,
# errors << {
# code: 2005,
# msg: I18n.t('errors.messages.repeating_postal_info')
# } and next if used.include?(attr)
# used << attr
@ -54,11 +54,16 @@ class Address < ActiveRecord::Base
return {} unless addr[:addr].is_a?(Hash)
{ country_id: Country.find_by(iso: addr[:addr][:cc]).try(:id),
city: addr[:addr][:city],
street: addr[:addr][:street][0],
street2: addr[:addr][:street][1],
street3: addr[:addr][:street][2],
street: pretty_street(addr[:addr][:street]), # [0],
# street2: addr[:addr][:street][1],
# street3: addr[:addr][:street][2],
zip: addr[:addr][:pc]
}.delete_if { |_k, v| v.nil? }
end
def pretty_street(param_street)
return param_street.join(',') if param_street.is_a?(Array)
param_street
end
end
end

View file

@ -0,0 +1,30 @@
module DomainVersionObserver
extend ActiveSupport::Concern
included do
after_save :delayed_whois_update
end
private
def delayed_whois_update
name = domain_name
return unless name
body = snapshot
delay.update_whois(name, body)
end
# not sure we need to pass in the params since i don't know if delayed job has access to
# all the regular attributes and stuff
def update_whois(domain_name, body)
wd = WhoisDomain.find_or_initialize_by(name: domain_name)
wd.body = body
wd.save!
end
def domain_name
name = reify.try(:name)
name = load_snapshot[:domain][:name] if event == 'create'
return name if name
end
end

View file

@ -18,10 +18,9 @@ class Contact < ActiveRecord::Base
accepts_nested_attributes_for :address, :disclosure
validates :code, :phone, :email, :ident, :address, :registrar, presence: true
validates :phone, :email, :ident, :address, :registrar, presence: true
validate :ident_must_be_valid
# validate :presence_of_one_address
validates :phone, format: /\+[0-9]{1,3}\.[0-9]{1,14}?/ # /\+\d{3}\.\d+/
validates :email, format: /@/
@ -37,6 +36,8 @@ class Contact < ActiveRecord::Base
# after_commit :domains_snapshot
after_update :domains_snapshot
after_destroy :domains_snapshot
before_create :generate_code
before_create :generate_auth_info
# scopes
scope :current_registrars, ->(id) { where(registrar_id: id) }
@ -96,6 +97,10 @@ class Contact < ActiveRecord::Base
self.code = SecureRandom.hex(4)
end
def generate_auth_info
self.auth_info = SecureRandom.hex(16)
end
# Find a way to use self.domains with contact
def domains_owned
Domain.where(owner_contact_id: id)
@ -149,16 +154,17 @@ class Contact < ActiveRecord::Base
# non-EPP
# EPP
def extract_attributes(ph, type = :create)
def extract_attributes(ph, _type = :create)
ph[:postalInfo] = ph[:postalInfo].first if ph[:postalInfo].is_a?(Array)
contact_hash = {
phone: ph[:voice],
ident: ph[:ident],
email: ph[:email],
fax: ph[:fax],
name: ph[:postalInfo].try(:[], :name),
org_name: ph[:postalInfo].try(:[], :org)
}
contact_hash[:auth_info] = ph[:authInfo][:pw] if type == :create
# contact_hash[:auth_info] = ph[:authInfo][:pw] if type == :create
contact_hash.delete_if { |_k, v| v.nil? }
end

View file

@ -1,5 +1,6 @@
class DomainVersion < PaperTrail::Version
include UserEvents
include DomainVersionObserver if Setting.whois_enabled # unless Setting.whois_enabled
scope :deleted, -> { where(event: 'destroy') }
@ -7,6 +8,29 @@ class DomainVersion < PaperTrail::Version
self.sequence_name = :domain_version_id_seq
def load_snapshot
YAML.load(snapshot)
snapshot ? YAML.load(snapshot) : {}
end
def previous?
return true if previous
false
end
def name
name = reify.try(:name)
name = load_snapshot[:domain].try(:[], :name) unless name
name
end
def changed_elements
return [] unless previous?
@changes = []
@previous_snap = previous.load_snapshot
@snap = load_snapshot
[:owner_contact, :tech_contacts, :admin_contacts, :nameservers, :domain].each do |key|
@changes << key unless @snap[key] == @previous_snap[key]
end
@changes
end
end

View file

@ -0,0 +1,3 @@
class WhoisDomain < WhoisServer
self.table_name = 'domains'
end

View file

@ -0,0 +1,4 @@
class WhoisServer < ActiveRecord::Base
self.abstract_class = true
establish_connection :"#{Rails.env}_whois"
end

View file

@ -1,30 +0,0 @@
.row
.col-md-12
%h2= t('shared.contacts')
%hr
.row
.col-md-12
.table-responsive
%table.table.table-hover.table-bordered.table-condensed
%thead
%tr
%th{class: 'col-xs-2'}
= t('shared.name')
%th{class: 'col-xs-1'}
= t('shared.code')
%th{class: 'col-xs-1'}
= sort_link(@q, 'whodunnit', t('shared.whodunnit'))
%th{class: 'col-xs-2'}
= sort_link(@q, 'created_at', t('shared.created_at'))
%tbody
- @contacts.each do |version|
- contact = version.reify
- next unless contact
%tr
%td= contact.name #link_to(x, admin_contact_path(x))
%td= contact.code #link_to(x, admin_contact_path(x))
%td= link_to_whodunnit(version.whodunnit) if version
%td= l(version.created_at, format: :short) if version
.row
.col-md-12
= paginate @contacts

View file

@ -1,23 +0,0 @@
.row
.col-md-6
%dl.dl-horizontal
%dt= t('shared.name')
%dd= contact.name
%dt= t('shared.ident')
%dd= contact.ident
%dt= t('shared.phone')
%dd= contact.phone
%dt= t('shared.email')
%dd= contact.email
%dt= t('shared.fax')
%dd= contact.fax
%dt= t('shared.org_name')
%dd= contact.org_name
.col-md-6
%dl.dl-horizontal
- if contact.address
%dt= t('shared.city')
%dd= contact.address.city
%dt= t('shared.street')
%dd= contact.address.street

View file

@ -1,40 +0,0 @@
.row
.col-sm-6
%h2.text-center-xs= t('shared.contacts_history')
=# render 'search'
.col-sm-6
%h2.text-right.text-center-xs
= link_to(t('shared.deleted'), admin_contact_versions_path(deleted: true), class: 'btn btn-primary')
%hr
.row
.col-md-12
.table-responsive
%table.table.table-hover.table-bordered.table-condensed
%thead
%tr
%th{class: 'col-xs-2'}
= sort_link(@q, 'name', t('shared.name'))
%th{class: 'col-xs-1'}
= sort_link(@q, 'code', t('shared.code'))
%th{class: 'col-xs-1'}
whodunnit
= #sort_link(@q, 'ident', t('shared.identity_code'))
%th{class: 'col-xs-1'}
event
= #sort_link(@q, 'email', t('shared.email'))
%th{class: 'col-xs-2'}
created_at
%th{class: 'col-xs-1'}
= t('shared.action')
%tbody
- @contacts.each do |x|
%tr
%td= x.name #link_to(x, admin_contact_path(x))
%td= x.code #link_to(x, admin_contact_path(x))
%td= link_to_whodunnit(x.versions.last.whodunnit) if x.versions.last
%td= x.versions.last.event if x.versions.last
%td= l(x.versions.last.created_at, format: :short) if x.versions.last
%td= link_to(t('shared.history'), admin_contact_version_path(x), class: 'btn btn-primary btn-xs')
.row
.col-md-12
= paginate @contacts

View file

@ -1,40 +0,0 @@
.row
.col-sm-6
%h2.text-center-xs
= "#{t('shared.contact_details')}"
.col-sm-6
%h2.text-right.text-center-xs
%hr
.row
.col-md-12
.table-responsive
%table.table.table-hover.table-bordered.table-condensed
%thead
%tr
%th
whodunnit
%th
event
%th
created_at
%tbody
- @versions.each_with_index do |version, index|
- contact = version.reify(has_one: true)
- if contact
%tr.clickable{"data-target" => "#accordion-#{index}", "data-toggle" => "collapse"}
%td=version.whodunnit #contact.name if contact
%td=version.event #contact.ident if contact
%td=version.created_at #contact.email if contact
%tr
%td
.collapse{ id: "accordion-#{index}" }
= render 'admin/contact_versions/history', contact: contact
- else
%tr
%td=version.whodunnit #contact.name if contact
%td=version.event #contact.ident if contact
%td=version.created_at #contact.email if contact

View file

@ -2,26 +2,27 @@
.panel-heading
%h3.panel-title= t('shared.address')
.panel-body
%dl.dl-horizontal
%dt= t('shared.country')
%dd= @contact.address.country
- unless @contact.address.nil?
%dl.dl-horizontal
%dt= t('shared.country')
%dd= @contact.address.country
%dt= t('shared.city')
%dd= @contact.address.city
%dt= t('shared.city')
%dd= @contact.address.city
%dt= t('shared.street')
%dd= @contact.address.street
- if @contact.address.street2
%dt= t('shared.street')
%dd= @contact.address.street2
%dd= @contact.address.street
- if @contact.address.street3
%dt= t('shared.street')
%dd= @contact.address.street3
- if @contact.address.street2
%dt= t('shared.street')
%dd= @contact.address.street2
- if @contact.address.street3
%dt= t('shared.street')
%dd= @contact.address.street3
%dt= t('shared.zip')
%dd= @contact.address.zip
%dt= t('shared.zip')
%dd= @contact.address.zip

View file

@ -0,0 +1,24 @@
.row
.col-sm-12
%h2.text-center-xs= t('shared.jobs')
%hr
.row
.col-md-12
.table-responsive
%table.table.table-hover.table-bordered.table-condensed
%thead
%tr
%th{class: 'col-xs-2'}= t('shared.priority')
%th{class: 'col-xs-2'}= t('shared.attempts')
%th{class: 'col-xs-2'}= t('shared.last_error')
%th{class: 'col-xs-1'}= t('shared.run_at')
%th{class: 'col-xs-1'}= t('shared.created_at')
%tbody
- @jobs.each do |job|
%tr
%td= job.priority
%td= job.attempts
%td= job.last_error
%td= job.run_at
%td= job.created_at

View file

@ -1,30 +0,0 @@
.row
.col-md-12
%h2= t('shared.domains')
%hr
.row
.col-md-12
.table-responsive
%table.table.table-hover.table-bordered.table-condensed
%thead
%tr
%th{class: 'col-xs-2'}
= t('shared.name')
%th{class: 'col-xs-2'}
= t('shared.status')
%th{class: 'col-xs-1'}
= sort_link(@q, 'whodunnit', t('shared.whodunnit'))
%th{class: 'col-xs-2'}
= sort_link(@q, 'created_at', t('shared.created_at'))
%tbody
- @domains.each do |version|
- domain = version.reify
- next unless domain
%tr
%td= domain.name #link_to(x, admin_contact_path(x))
%td= domain.status #link_to(x, admin_contact_path(x))
%td= link_to_whodunnit(version.whodunnit) if version
%td= l(version.created_at, format: :short) if version
.row
.col-md-12
= paginate @domains

View file

@ -0,0 +1,48 @@
%td{ class: changes.include?(:owner_contact) ? 'edit-highlight' : 'no-highlight' }
- if children[:owner_contact]
%p{:style => "font-size:x-small;"}
= children[:owner_contact][:name]
= ","
= children[:owner_contact][:phone]
= ","
= children[:owner_contact][:email]
= ","
= children[:owner_contact][:code]
%td{ class: changes.include?(:admin_contacts) ? 'edit-highlight' : 'no-highlight' }
- if children[:admin_contacts]
- children[:admin_contacts].each do |ac|
%p{:style => "font-size:x-small;"}
= ac[:name]
= ","
= ac[:phone]
= ","
= ac[:email]
= ","
= ac[:code]
%td{ class: changes.include?(:tech_contacts) ? 'edit-highlight' : 'no-highlight' }
- if children[:tech_contacts]
- children[:tech_contacts].each do |tc|
%p{:style => "font-size:x-small;"}
= tc[:name]
= ","
= tc[:phone]
= ","
= tc[:email]
= ","
= tc[:code]
%td{ class: changes.include?(:nameservers) ? 'edit-highlight' : 'no-highlight' }
- if children[:nameservers]
- children[:nameservers].each do |ns|
%p{:style => "font-size:x-small;"}
= ns[:hostname]
= ","
= ns[:ipv4] || ns[:ipv6]
%td
%p{ :style => 'font-size:x-small;' }
= l(version.created_at, format: :short)
= whodunnit_with_protocol(version.whodunnit)
= version.event

View file

@ -8,31 +8,20 @@
%table.table.table-hover.table-bordered.table-condensed
%thead
%tr
%th{class: 'col-xs-2'}
= sort_link(@q, 'name')
%th{class: 'col-xs-2'}
= sort_link(@q, 'registrar_name', t('shared.registrar'))
%th{class: 'col-xs-2'}
= sort_link(@q, 'owner_contact_name', t('shared.owner'))
%th{class: 'col-xs-1'}
= t('shared.whodunnit')
%th{class: 'col-xs1'}
= t('shared.event')
%th{class: 'col-xs1'}
= t('shared.created_at')
%th{class: 'col-xs1'}
= t('shared.action')
= t('shared.name')
%th{class: 'col-xs-1'}
= sort_link(@q, 'whodunnit')
%th{class: 'col-xs-1'}
= sort_link(@q, 'created_at')
%tbody
- @domains.each do |domain|
- obj = domain.reify
%tr
%td= domain.name
%td= domain.registrar.name if domain.registrar
%td= domain.owner_contact.name if domain.owner_contact
%td= link_to_whodunnit(domain.versions.last.whodunnit) if domain.versions.last
%td= domain.versions.last.event if domain.versions.last
%td= l(domain.versions.last.created_at, format: :short) if domain.versions.last
%td= link_to(t('shared.history'), admin_domain_version_path(domain), class: 'btn btn-primary btn-xs')
%td= link_to(obj.name, admin_domain_version_path(obj))
%td= whodunnit_with_protocol(domain.whodunnit) unless domain.whodunnit.nil?
%td= l(obj.created_at, format: :short)
.row
.col-md-12

View file

@ -1,7 +1,7 @@
.row
.col-sm-6
%h2.text-center-xs
= "#{t('shared.contact_details')}"
= "#{t('shared.domain_history')} for " + @name.to_s
.col-sm-6
%h2.text-right.text-center-xs
@ -9,24 +9,20 @@
.row
.col-md-12
.table-responsive
%table.table.table-hover.table-bordered.table-condensed
%table.table-hover.table-bordered.table-condensed
%thead
%tr
%th
whodunnit
%th
event
%th
created_at
%th{class: 'col-xs-2'}= t(:'shared.owner_contact')
%th{class: 'col-xs-2'}= t(:'shared.admin_contacts')
%th{class: 'col-xs-2'}= t(:'shared.tech_contacts')
%th{class: 'col-xs-2'}= t(:'shared.nameservers')
%th{class: 'col-xs-1'}= t(:'shared.changes_info')
%tbody
- @versions.each_with_index do |version, index|
- domain = version.reify(has_multiple: true)
- if domain
= render 'admin/domain_versions/history', version: version, index: index, domain: domain
- else
%tr
%td=version.whodunnit #contact.name if contact
%td=version.event #contact.ident if contact
%td=version.created_at #contact.email if contact
- @versions.each do |version|
%tr
- children = version.load_snapshot
- next unless children.is_a?(Hash)
- children = HashWithIndifferentAccess.new(children)
- changes = version.changed_elements
= render 'admin/domain_versions/version', children: children, version: version, changes: changes

View file

@ -29,6 +29,7 @@
= sort_link(@q, 'owner_contact_name', t('shared.owner'))
%th{class: 'col-xs-2'}
= sort_link(@q, 'valid_to', t('shared.valid_to'))
%th{class: 'col-xs-1'}= t('shared.history')
%tbody
- @domains.each do |x|
%tr
@ -36,6 +37,7 @@
%td= link_to(x.registrar, root_path) if x.registrar
%td= link_to(x.owner_contact, [:admin, x.owner_contact])
%td= l(x.valid_to, format: :short)
%td= button_to(t(:'shared.history'), admin_domain_version_path(x.id), method: :get)
.row
.col-md-12
= paginate @domains

View file

@ -1,14 +1,15 @@
address = @contact.address
xml.tag!('contact:postalInfo', type: 'int') do # TODO instance method of defining type
xml.tag!('contact:name', @contact.name) if @contact.disclosure.int_name
xml.tag!('contact:org', @contact.org_name) if @contact.disclosure.int_org_name
if @contact.disclosure.int_addr
xml.tag!('contact:addr') do
xml.tag!('contact:street', address.street) if address.street
xml.tag!('contact:street', address.street2) if address.street2
xml.tag!('contact:street', address.street3) if address.street3
xml.tag!('contact:cc', address.try(:country).try(:iso)) unless address.try(:country).nil?
end
xml.tag!('contact:postalInfo', type: 'int') do
xml.tag!('contact:name', @contact.name)# if @contact.disclosure.try(:int_name)
xml.tag!('contact:org', @contact.org_name)# if @contact.disclosure.try(:int_org_name)
#if @contact.disclosure.try(:int_addr)
xml.tag!('contact:addr') do
xml.tag!('contact:street', address.street) if address.street
#xml.tag!('contact:street', address.street2) if address.street2
#xml.tag!('contact:street', address.street3) if address.street3
xml.tag!('contact:cc', address.try(:country).try(:iso)) unless address.try(:country).nil?
xml.tag!('contact:city', address.city)
end
#end
end

View file

@ -7,9 +7,10 @@ xml.epp_head do
xml.resData do
xml.tag!('contact:chkData', 'xmlns:contact' => 'urn:ietf:params:xml:ns:contact-1.0') do
xml << render('/epp/contacts/postal_info')
xml.tag!('contact:voice', @contact.phone) if @contact.disclosure.phone
xml.tag!('contact:fax', @contact.fax) if @contact.disclosure.fax
xml.tag!('contact:email', @contact.email) if @contact.disclosure.email
xml.tag!('contact:id', @contact.code)
xml.tag!('contact:voice', @contact.phone) #if @contact.disclosure.try(:phone)
xml.tag!('contact:fax', @contact.fax) #if @contact.disclosure.try(:fax)
xml.tag!('contact:email', @contact.email) #if @contact.disclosure..try(:email)
xml.tag!('contact:clID', @current_epp_user.username) if @current_epp_user
xml.tag!('contact:crID', @contact.cr_id ) if @contact.cr_id
xml.tag!('contact:crDate', @contact.created_at)

View file

@ -46,22 +46,12 @@
%li
= link_to t('shared.users'), admin_users_path
%li.dropdown
%a.dropdown-toggle{"data-toggle" => "dropdown", href: "#"}
= t('shared.archives')
%span.caret
%ul.dropdown-menu{role: "menu"}
%li.dropdown-header= t('shared.domain')
%li
= link_to t('shared.versions'), admin_domain_versions_path
%li
= link_to t('shared.deleted'), admin_domain_histories_path
%li
= link_to t('shared.domains_history'), admin_domain_versions_path
%li
= link_to t('shared.jobs'), admin_delayed_jobs_path
%li.dropdown-header= t('shared.contact')
%li
= link_to t('shared.versions'), admin_contact_versions_path
%li
= link_to t('shared.deleted'), admin_contact_histories_path
%ul.nav.navbar-nav.navbar-right
%li= link_to t('shared.log_out', user: current_user), '/logout'

5
bin/delayed_job Executable file
View file

@ -0,0 +1,5 @@
#!/usr/bin/env ruby
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
require 'delayed/command'
Delayed::Command.new(ARGV).daemonize

View file

@ -17,3 +17,9 @@ test:
production:
<<: *default
database: registry_production
development_whois:
database: whois_development
test_whois:
database: test_whois

View file

@ -85,6 +85,8 @@ task deploy: :environment do
to :launch do
queue "mkdir -p #{deploy_to}/current/tmp; touch #{deploy_to}/current/tmp/restart.txt"
queue 'RAILS_ENV=production bin/delayed_job stop'
queue 'RAILS_ENV=production bin/delayed_job start'
end
end
end

View file

@ -263,6 +263,7 @@ en:
registrar: 'Registrar'
owner: 'Owner'
domain_details: 'Domain details'
domain_history: 'Domain history'
registered_at: 'Registered at'
password: 'Password'
valid_from: 'Valid from'

View file

@ -29,11 +29,9 @@ Rails.application.routes.draw do
resources :users
resources :epp_users
resources :contact_versions
resources :domain_versions
resources :contact_histories
resources :domain_histories
resources :delayed_jobs
root 'domains#index'

View file

@ -0,0 +1,22 @@
class CreateDelayedJobs < ActiveRecord::Migration
def self.up
create_table :delayed_jobs, :force => true do |table|
table.integer :priority, :default => 0, :null => false # Allows some jobs to jump to the front of the queue
table.integer :attempts, :default => 0, :null => false # Provides for retries, but still fail eventually.
table.text :handler, :null => false # YAML-encoded string of the object that will do work
table.text :last_error # reason for last failure (See Note below)
table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
table.datetime :locked_at # Set when a client is working on this object
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
table.string :locked_by # Who is working on this object (if locked)
table.string :queue # The name of the queue this job is in
table.timestamps
end
add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
end
def self.down
drop_table :delayed_jobs
end
end

View file

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20141105150721) do
ActiveRecord::Schema.define(version: 20141111105931) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -91,6 +91,22 @@ ActiveRecord::Schema.define(version: 20141105150721) do
t.datetime "updated_at"
end
create_table "delayed_jobs", force: true do |t|
t.integer "priority", default: 0, null: false
t.integer "attempts", default: 0, null: false
t.text "handler", null: false
t.text "last_error"
t.datetime "run_at"
t.datetime "locked_at"
t.datetime "failed_at"
t.string "locked_by"
t.string "queue"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority", using: :btree
create_table "delegation_signers", force: true do |t|
t.integer "domain_id"
t.string "key_tag"

View file

@ -77,3 +77,5 @@ Setting.ns_min_count = 2
Setting.ns_max_count = 11
Setting.transfer_wait_time = 0
# Setting.whois_enabled = true only uncomment this if you wish whois

23
doc/whois.rm Normal file
View file

@ -0,0 +1,23 @@
Connection with whois
------------------------------------
The easiest way to get started without whois is to change Settings.whois_enabled to false. But like expected,
that disables whois (effects should fully be loaded after restarting the app)
What whois_enabled=false does is that the whois callback does not get included.
Delayed jobs migration and everything else will still be installed tho.
If you wish to use the whois module, tho, you need a whois database looking something like this
```ruby
create_table :domains do |t|
t.string :name
t.text :body
t.timestamps
end
```
NB! Migration with rake tasks is available in whois app repo.
For development, delayed_job queue can be handled by rake task
`rake jobs:work` or if you wish to be fancy you can use a daemon with `bin/delayed_job start`
``

View file

@ -1,28 +1,89 @@
require 'net/ssh'
require 'net/scp'
desc 'Commands for whois'
desc 'generate whois files'
desc 'generate whois file(s)'
task 'whois:generate' => :environment do
Dir.mkdir('./tmp/whois') unless File.exist?('./tmp/whois') # a folder for ze stuff
letter = ENV['letter']
@path = 'tmp/whois/'
letter.nil? ? generate_whois : whois_data(letter)
end
alphabet = (('a'..'z').to_a << %w(ö õ ü ä)).flatten!
@domains = {}
alphabet.each do |letter|
domains = Domain.where(['name LIKE ?', "#{letter}%"])
@domains[letter] = {}
# TODO: refactor
desc 'Generate and copy one file'
task 'whois:handle_domain' => :environment do
letter = ENV['letter']
@path = 'tmp/whois/'
whois_data(letter)
copy_files(["tmp/whois/#{letter}_domain.yaml"])
end
domains.each do |domain|
@domains[letter][domain.name] = {
valid_to: domain.valid_to,
status: domain.status,
contacts: [
{ name: domain.owner_contact.name, email: domain.owner_contact.email },
{ registrar: domain.registrar.name, address: domain.registrar.address }
]
}
end
desc 'copy whois files'
task 'whois:scp' => :environment do
letter = ENV['letter']
files = letter.nil? ? Dir['tmp/whois/*_domain.yaml'] : ["tmp/whois/#{letter}_domain.yaml"]
unless files.present?
Rails.logger.warn("tmp/whois/ is empty, no files copied at #{Time.now}")
return
end
@domains.each do |k, v|
File.open("tmp/whois/#{k}_domain.yaml", 'w') { |f| f.write(v.to_yaml) }
copy_files(files)
end
# Generates whois data for all domains
def generate_whois
alphabet = (('a'..'z').to_a << %w(ö õ ü ä)).flatten!
alphabet.each do |letter|
whois_data(letter)
end
end
# Generates whois data for a domains starting with 'letter'
def whois_data(letter)
data = {}
domains = Domain.where(['name LIKE ?', "#{letter}%"])
domains.each do |domain|
data[domain.name] = {
valid_to: domain.valid_to,
status: domain.status,
contacts: [
{ name: domain.owner_contact.name, email: domain.owner_contact.email },
{ registrar: domain.registrar.name, address: domain.registrar.address }
]
}
end
File.open(@path + "#{letter}_domain.yaml", 'w') { |f| f.write(data.to_yaml) }
end
# copies files from paths passed in ( files = [ path_to_file, path_to_another_file ] )
def copy_files(files)
connection_info
generate_sum
Net::SSH.start(@host, @username, port: @port) do |session|
session.scp.upload!('tmp/whois/checklist.chk', @remote_path)
files.each do |file|
session.scp.upload!(file, @remote_path) do |_ch, name, sent, total|
puts "#{name}: #{sent}/#{total}"
end
end
end
end
def generate_sum
result = `( cd tmp/whois/; md5sum *.yaml > checklist.chk )`
Rails.logger.info(result)
end
# Describes the connection info for scp, ssh keys have to in order (passwordless login) for this to work
# TODO: move to settings
def connection_info
@host = '95.215.45.231'
@username = 'whois'
@port = 22
@remote_path = 'app/shared/data/'
end

View file

@ -1,6 +1,16 @@
require 'rails_helper'
describe 'EPP Contact', epp: true do
before do
# we don't really care about the code validations here, it's done in models
# dynamic Contact.code just makes it harder to test EPP
Contact.skip_callback(:create, :before, :generate_code)
end
after do
Contact.set_callback(:create, :before, :generate_code)
end
let(:server_zone) { Epp::Server.new({ server: 'localhost', tag: 'zone', password: 'ghyt9e4fu', port: 701 }) }
let(:server_elkdata) { Epp::Server.new({ server: 'localhost', tag: 'elkdata', password: 'ghyt9e4fu', port: 701 }) }
let(:elkdata) { Fabricate(:registrar, { name: 'Elkdata', reg_no: '123' }) }
@ -17,15 +27,13 @@ describe 'EPP Contact', epp: true do
context 'create command' do
it 'fails if request is invalid' do
response = epp_request(contact_create_xml({ authInfo: [false], addr: { cc: false, city: false } }), :xml)
response = epp_request(contact_create_xml({ addr: { cc: false, city: false } }), :xml)
expect(response[:results][0][:result_code]).to eq('2003')
expect(response[:results][1][:result_code]).to eq('2003')
expect(response[:results][2][:result_code]).to eq('2003')
expect(response[:results][0][:msg]).to eq('Required parameter missing: pw')
expect(response[:results][1][:msg]).to eq('Required parameter missing: city')
expect(response[:results][2][:msg]).to eq('Required parameter missing: cc')
expect(response[:results].count).to eq 3
expect(response[:results][0][:msg]).to eq('Required parameter missing: city')
expect(response[:results][1][:msg]).to eq('Required parameter missing: cc')
expect(response[:results].count).to eq 2
end
it 'successfully creates a contact' do
@ -44,8 +52,8 @@ describe 'EPP Contact', epp: true do
expect(Contact.first.ident_type).to eq 'op'
expect(Contact.first.address.street).to eq('123 Example Dr.')
expect(Contact.first.address.street2).to eq('Suite 100')
expect(Contact.first.address.street3).to eq nil
# expect(Contact.first.address.street2).to eq('Suite 100')
# expect(Contact.first.address.street3).to eq nil
end
it 'successfully adds registrar' do
@ -140,15 +148,16 @@ describe 'EPP Contact', epp: true do
expect(response[:results][1][:msg]).to eq('Email is invalid')
end
it 'updates disclosure items' do
Fabricate(:contact, code: 'sh8013', auth_info: '2fooBAR', registrar: zone, created_by_id: EppUser.first.id,
disclosure: Fabricate(:contact_disclosure, phone: true, email: true))
epp_request('contacts/update.xml')
expect(Contact.last.disclosure.phone).to eq(false)
expect(Contact.last.disclosure.email).to eq(false)
expect(Contact.count).to eq(1)
end
# it 'updates disclosure items', pending: true do
# pending 'Disclosure needs to be remodeled a bit'
# Fabricate(:contact, code: 'sh8013', auth_info: '2fooBAR', registrar: zone, created_by_id: EppUser.first.id,
# disclosure: Fabricate(:contact_disclosure, phone: true, email: true))
# epp_request('contacts/update.xml')
#
# expect(Contact.last.disclosure.phone).to eq(false)
# expect(Contact.last.disclosure.email).to eq(false)
# expect(Contact.count).to eq(1)
# end
end
context 'delete command' do
@ -252,7 +261,8 @@ describe 'EPP Contact', epp: true do
end
it 'doesn\'t disclose private elements' do
it 'doesn\'t disclose private elements', pending: true do
pending 'Disclosure needs to have some of the details worked out'
Fabricate(:contact, code: 'info-4444', auth_info: '2fooBAR',
disclosure: Fabricate(:contact_disclosure, email: false, phone: false))
response = epp_request('contacts/info.xml')
@ -265,7 +275,8 @@ describe 'EPP Contact', epp: true do
expect(contact.css('name').present?).to be(true)
end
it 'doesn\'t display unassociated object' do
it 'doesn\'t display unassociated object', pending: true do
pending 'Have to rework contact info request to have optional password requirement'
Fabricate(:contact, code: 'info-4444')
response = epp_request('contacts/info.xml')

View file

@ -1,6 +1,16 @@
require 'rails_helper'
describe 'EPP Domain', epp: true do
before do
# we don't really care about the code validations here, it's done in models
# dynamic Contact.code just makes it harder to test EPP
Contact.skip_callback(:create, :before, :generate_code)
end
after do
Contact.set_callback(:create, :before, :generate_code)
end
let(:server_zone) { Epp::Server.new({ server: 'localhost', tag: 'zone', password: 'ghyt9e4fu', port: 701 }) }
let(:server_elkdata) { Epp::Server.new({ server: 'localhost', tag: 'elkdata', password: 'ghyt9e4fu', port: 701 }) }
let(:elkdata) { Fabricate(:registrar, { name: 'Elkdata', reg_no: '123' }) }

View file

@ -9,13 +9,12 @@ describe Address, '.extract_params' do
it 'returns params hash' do
Fabricate(:country, iso: 'EE')
ph = { postalInfo: { name: 'fred', addr: { cc: 'EE', city: 'Village', street: %w(street1 street2) } } }
ph = { postalInfo: { name: 'fred', addr: { cc: 'EE', city: 'Village', street: 'street1' } } }
expect(Address.extract_attributes(ph[:postalInfo])).to eq({
address_attributes: {
country_id: Country.find_by(iso: 'EE').id,
city: 'Village',
street: 'street1',
street2: 'street2'
street: 'street1'
}
})
end

View file

@ -21,7 +21,6 @@ describe Contact do
expect(@contact.valid?).to eq false
expect(@contact.errors.messages).to match_array({
code: ['Required parameter missing - code'],
phone: ['Required parameter missing - phone', 'Phone nr is invalid'],
email: ['Required parameter missing - email', 'Email is invalid'],
ident: ['Required parameter missing - ident'],
@ -38,6 +37,43 @@ describe Contact do
expect(@contact.valid?).to be true
end
end
context 'with callbacks' do
before(:each) { @contact = Fabricate.build(:contact, code: '123asd', auth_info: 'qwe321') }
context 'after create' do
it 'should generate code' do
expect(@contact.code).to eq('123asd')
@contact.save!
expect(@contact.code).to_not eq('123asd')
end
it 'should generate password' do
expect(@contact.auth_info).to eq('qwe321')
@contact.save!
expect(@contact.auth_info).to_not eq('qwe321')
end
end
context 'after update' do
before(:each) do
@contact.save!
@code = @contact.code
@auth_info = @contact.auth_info
end
it 'should not generate new code' do
@contact.update_attributes(name: 'qevciherot23')
expect(@contact.code).to eq(@code)
end
it 'should not generate new auth_info' do
@contact.update_attributes(name: 'fvrsgbqevciherot23')
expect(@contact.auth_info).to eq(@auth_info)
end
end
end
end
describe Contact, '#relations_with_domain?' do
@ -96,8 +132,7 @@ describe Contact, '.extract_params' do
postalInfo: { name: 'fred', addr: { cc: 'EE' } } }
expect(Contact.extract_attributes(ph)).to eq({
name: 'fred',
email: 'jdoe@example.com',
auth_info: 'asde'
email: 'jdoe@example.com'
})
end
end
@ -116,15 +151,18 @@ describe Contact, '.check_availability' do
end
it 'should return in_use and available codes' do
response = Contact.check_availability(%w(asd12 asd13 asd14))
code = Contact.first.code
code_ = Contact.last.code
response = Contact.check_availability([code, code_, 'asd14'])
expect(response.class).to be Array
expect(response.length).to eq(3)
expect(response[0][:avail]).to eq(0)
expect(response[0][:code]).to eq('asd12')
expect(response[0][:code]).to eq(code)
expect(response[1][:avail]).to eq(0)
expect(response[1][:code]).to eq('asd13')
expect(response[1][:code]).to eq(code_)
expect(response[2][:avail]).to eq(1)
expect(response[2][:code]).to eq('asd14')

View file

@ -15,17 +15,35 @@ describe DomainVersion do
context 'when domain is created' do
it('creates a domain version') { expect(DomainVersion.count).to eq(1) }
it('has a snapshot') { expect(DomainVersion.first.snapshot).not_to be_empty }
it 'has a snapshot with correct info' do
expect(DomainVersion.last.load_snapshot).to eq({
admin_contacts: [{ name: 'admin_contact 1', phone: '+372.12345678',
code: 'qwe', ident: '37605030299', email: 'admin1@v.ee' }],
domain: { name: 'version.ee', status: nil },
nameservers: [{ hostname: 'ns.test.ee', ipv4: nil, ipv6: nil }],
owner_contact: { name: 'owner_contact', phone: '+372.12345678',
code: 'asd', ident: '37605030299', email: 'owner1@v.ee' },
tech_contacts: [{ name: 'tech_contact 1', phone: '+372.12345678',
code: 'zxc', ident: '37605030299', email: 'tech1@v.ee' }]
})
it('has a snapshot with admin_contacts') do
expect(DomainVersion.last.load_snapshot[:admin_contacts].first).to include(
name: 'admin_contact 1', phone: '+372.12345678', ident: '37605030299', email: 'admin1@v.ee'
)
end
it('has a snapshot with domain') do
expect(DomainVersion.last.load_snapshot[:domain]).to include(
name: 'version.ee', status: nil
)
end
it('has a snapshot with nameservers') do
expect(DomainVersion.last.load_snapshot[:nameservers]).to include(
hostname: 'ns.test.ee', ipv4: nil, ipv6: nil
)
end
it('has a snapshot with owner contact') do
expect(DomainVersion.last.load_snapshot[:owner_contact]).to include(
name: 'owner_contact', phone: '+372.12345678', ident: '37605030299', email: 'owner1@v.ee'
)
end
it('has a snapshot with tech contacts') do
expect(DomainVersion.last.load_snapshot[:tech_contacts].first).to include(
name: 'tech_contact 1', phone: '+372.12345678', ident: '37605030299', email: 'tech1@v.ee'
)
end
end
@ -34,14 +52,15 @@ describe DomainVersion do
expect(DomainVersion.count).to eq(1)
Domain.first.destroy
expect(DomainVersion.count).to eq(2)
expect(DomainVersion.last.load_snapshot).to eq({
expect(DomainVersion.last.load_snapshot).to include({
admin_contacts: [],
domain: { name: 'version.ee', status: nil },
nameservers: [],
owner_contact: { name: 'owner_contact', phone: '+372.12345678',
code: 'asd', ident: '37605030299', email: 'owner1@v.ee' },
tech_contacts: []
})
expect(DomainVersion.last.load_snapshot[:owner_contact]).to include(
{ name: 'owner_contact', phone: '+372.12345678', ident: '37605030299', email: 'owner1@v.ee' }
)
end
end
@ -80,15 +99,22 @@ describe DomainVersion do
expect(DomainVersion.count).to eq(1)
Contact.find_by(name: 'tech_contact 1').destroy
expect(DomainVersion.count).to eq(2)
expect(DomainVersion.last.load_snapshot).to eq({
admin_contacts: [{ name: 'admin_contact 1', phone: '+372.12345678',
code: 'qwe', ident: '37605030299', email: 'admin1@v.ee' }],
domain: { name: 'version.ee', status: nil },
nameservers: [{ hostname: 'ns.test.ee', ipv4: nil, ipv6: nil }],
owner_contact: { name: 'owner_contact', phone: '+372.12345678',
code: 'asd', ident: '37605030299', email: 'owner1@v.ee' },
tech_contacts: []
})
expect(DomainVersion.last.load_snapshot[:admin_contacts].size).to eq(1)
expect(DomainVersion.last.load_snapshot[:admin_contacts].first).to include(
name: 'admin_contact 1', phone: '+372.12345678', ident: '37605030299', email: 'admin1@v.ee'
)
expect(DomainVersion.last.load_snapshot[:domain]).to eq(
{ name: 'version.ee', status: nil }
)
expect(DomainVersion.last.load_snapshot[:nameservers].size).to eq(1)
expect(DomainVersion.last.load_snapshot[:nameservers].first).to include(
hostname: 'ns.test.ee', ipv4: nil, ipv6: nil
)
expect(DomainVersion.last.load_snapshot[:owner_contact]).to include(
{ name: 'owner_contact', phone: '+372.12345678', ident: '37605030299', email: 'owner1@v.ee' }
)
expect(DomainVersion.last.load_snapshot[:tech_contacts]).to eq([])
end
it 'nameserver creates a version' do
@ -96,18 +122,26 @@ describe DomainVersion do
Domain.last.nameservers.last.destroy
expect(DomainVersion.count).to eq(3)
expect(Domain.last.nameservers.count).to eq(1)
expect(DomainVersion.last.load_snapshot).to eq(
admin_contacts: [{ name: 'admin_contact 1', phone: '+372.12345678',
code: 'qwe', ident: '37605030299', email: 'admin1@v.ee' }],
domain: { name: 'version.ee', status: nil },
nameservers: [{ hostname: 'ns.test.ee', ipv4: nil, ipv6: nil }],
owner_contact: { name: 'owner_contact', phone: '+372.12345678',
code: 'asd', ident: '37605030299', email: 'owner1@v.ee' },
tech_contacts: [{ name: 'tech_contact 1', phone: '+372.12345678',
code: 'zxc', ident: '37605030299', email: 'tech1@v.ee' }]
expect(DomainVersion.last.load_snapshot[:admin_contacts].size).to eq(1)
expect(DomainVersion.last.load_snapshot[:admin_contacts].first).to include(
name: 'admin_contact 1', phone: '+372.12345678', ident: '37605030299', email: 'admin1@v.ee'
)
expect(DomainVersion.last.load_snapshot[:domain]).to eq(
{ name: 'version.ee', status: nil }
)
expect(DomainVersion.last.load_snapshot[:nameservers].size).to eq(1)
expect(DomainVersion.last.load_snapshot[:nameservers].first).to include(
hostname: 'ns.test.ee', ipv4: nil, ipv6: nil
)
expect(DomainVersion.last.load_snapshot[:owner_contact]).to include(
{ name: 'owner_contact', phone: '+372.12345678', ident: '37605030299', email: 'owner1@v.ee' }
)
expect(DomainVersion.last.load_snapshot[:tech_contacts].size).to eq(1)
expect(DomainVersion.last.load_snapshot[:tech_contacts].first).to include(
name: 'tech_contact 1', phone: '+372.12345678', ident: '37605030299', email: 'tech1@v.ee'
)
end
end
context 'when editing children' do
@ -125,16 +159,24 @@ describe DomainVersion do
expect(DomainVersion.count).to eq(3)
Contact.find_by(name: 'admin_contact 1').update_attributes!(name: 'edited admin_contact')
expect(DomainVersion.count).to eq(4)
expect(DomainVersion.last.load_snapshot).to eq({
admin_contacts: [{ name: 'edited admin_contact', phone: '+372.12345678',
code: 'qwe', ident: '37605030299', email: 'admin1@v.ee' }],
domain: { name: 'version.ee', status: nil },
nameservers: [{ hostname: 'ns.test.ee', ipv4: nil, ipv6: nil }],
owner_contact: { name: 'edited owner_contact', phone: '+372.12345678',
code: 'asd', ident: '37605030299', email: 'owner1@v.ee' },
tech_contacts: [{ name: 'edited tech_contact', phone: '+372.12345678',
code: 'zxc', ident: '37605030299', email: 'tech1@v.ee' }]
})
expect(DomainVersion.last.load_snapshot[:admin_contacts].size).to eq(1)
expect(DomainVersion.last.load_snapshot[:admin_contacts].first).to include(
name: 'edited admin_contact', phone: '+372.12345678', ident: '37605030299', email: 'admin1@v.ee'
)
expect(DomainVersion.last.load_snapshot[:domain]).to eq(
{ name: 'version.ee', status: nil }
)
expect(DomainVersion.last.load_snapshot[:nameservers].size).to eq(1)
expect(DomainVersion.last.load_snapshot[:nameservers].first).to include(
hostname: 'ns.test.ee', ipv4: nil, ipv6: nil
)
expect(DomainVersion.last.load_snapshot[:owner_contact]).to include(
{ name: 'edited owner_contact', phone: '+372.12345678', ident: '37605030299', email: 'owner1@v.ee' }
)
expect(DomainVersion.last.load_snapshot[:tech_contacts].size).to eq(1)
expect(DomainVersion.last.load_snapshot[:tech_contacts].first).to include(
name: 'edited tech_contact', phone: '+372.12345678', ident: '37605030299', email: 'tech1@v.ee'
)
end
end
end

View file

@ -42,8 +42,8 @@ module EppContactXmlBuilder
unless xml_params[:addr] == [false]
xml.tag!('contact:addr') do
xml.tag!('contact:street', xml_params[:addr][:street]) unless xml_params[:addr][:street] == false
xml.tag!('contact:street', xml_params[:addr][:street2]) unless xml_params[:addr][:street2] == false
xml.tag!('contact:street', xml_params[:addr][:street3]) unless xml_params[:addr][:street3] == false
#xml.tag!('contact:street', xml_params[:addr][:street2]) unless xml_params[:addr][:street2] == false
#xml.tag!('contact:street', xml_params[:addr][:street3]) unless xml_params[:addr][:street3] == false
xml.tag!('contact:city', xml_params[:addr][:city]) unless xml_params[:addr][:city] == false
xml.tag!('contact:sp', xml_params[:addr][:sp]) unless xml_params[:addr][:sp] == false
xml.tag!('contact:pc', xml_params[:addr][:pc]) unless xml_params[:addr][:pc] == false
@ -110,8 +110,8 @@ module EppContactXmlBuilder
unless xml_params[:chg][:postalInfo][:addr] == false
xml.tag!('contact:addr') do
xml.tag!('contact:street', xml_params[:chg][:postalInfo][:addr][:street]) unless xml_params[:chg][:postalInfo][:addr][:street] == false
xml.tag!('contact:street', xml_params[:chg][:postalInfo][:addr][:street2]) unless xml_params[:chg][:postalInfo][:addr][:street2] == false
xml.tag!('contact:street', xml_params[:chg][:postalInfo][:addr][:street3]) unless xml_params[:chg][:postalInfo][:addr][:street3] == false
#xml.tag!('contact:street', xml_params[:chg][:postalInfo][:addr][:street2]) unless xml_params[:chg][:postalInfo][:addr][:street2] == false
#xml.tag!('contact:street', xml_params[:chg][:postalInfo][:addr][:street3]) unless xml_params[:chg][:postalInfo][:addr][:street3] == false
xml.tag!('contact:city', xml_params[:chg][:postalInfo][:addr][:city]) unless xml_params[:chg][:postalInfo][:addr][:city] == false
xml.tag!('contact:sp', xml_params[:chg][:postalInfo][:addr][:sp]) unless xml_params[:chg][:postalInfo][:addr][:sp] == false
xml.tag!('contact:pc', xml_params[:chg][:postalInfo][:addr][:pc]) unless xml_params[:chg][:postalInfo][:addr][:pc] == false