mirror of
https://github.com/internetee/registry.git
synced 2025-05-16 17:37:17 +02:00
Merge pull request #620 from internetee/revert-551d1799d1782a9dbf5edfb57a0fa4c5fe6bef83
Revert "Revert "Registry 569""
This commit is contained in:
commit
ca13c08ea8
49 changed files with 2462 additions and 315 deletions
|
@ -27,6 +27,7 @@ engines:
|
||||||
- HACK
|
- HACK
|
||||||
rubocop:
|
rubocop:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
channel: rubocop-0-49
|
||||||
reek:
|
reek:
|
||||||
enabled: true
|
enabled: true
|
||||||
checks:
|
checks:
|
||||||
|
|
1
Gemfile
1
Gemfile
|
@ -104,6 +104,7 @@ gem 'activerecord-import', '0.7.0' # for inserting dummy data
|
||||||
# for generating pdf
|
# for generating pdf
|
||||||
gem 'pdfkit', '0.6.2'
|
gem 'pdfkit', '0.6.2'
|
||||||
gem 'jquery-ui-rails', '5.0.5'
|
gem 'jquery-ui-rails', '5.0.5'
|
||||||
|
gem 'active_model-errors_details' # Backport from Rails 5, https://github.com/rails/rails/pull/18322
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
gem 'spring'
|
gem 'spring'
|
||||||
|
|
|
@ -79,6 +79,9 @@ GEM
|
||||||
erubis (~> 2.7.0)
|
erubis (~> 2.7.0)
|
||||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||||
|
active_model-errors_details (1.3.1)
|
||||||
|
activemodel (>= 3.2.13, < 5.0.0)
|
||||||
|
activesupport
|
||||||
activejob (4.2.7.1)
|
activejob (4.2.7.1)
|
||||||
activesupport (= 4.2.7.1)
|
activesupport (= 4.2.7.1)
|
||||||
globalid (>= 0.3.0)
|
globalid (>= 0.3.0)
|
||||||
|
@ -489,6 +492,7 @@ PLATFORMS
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
SyslogLogger (= 2.0)
|
SyslogLogger (= 2.0)
|
||||||
|
active_model-errors_details
|
||||||
activerecord-import (= 0.7.0)
|
activerecord-import (= 0.7.0)
|
||||||
airbrake
|
airbrake
|
||||||
autodoc
|
autodoc
|
||||||
|
|
|
@ -2,6 +2,7 @@ module Admin
|
||||||
class ContactsController < BaseController
|
class ContactsController < BaseController
|
||||||
load_and_authorize_resource
|
load_and_authorize_resource
|
||||||
before_action :set_contact, only: [:show]
|
before_action :set_contact, only: [:show]
|
||||||
|
helper_method :ident_types
|
||||||
|
|
||||||
def index
|
def index
|
||||||
params[:q] ||= {}
|
params[:q] ||= {}
|
||||||
|
@ -79,5 +80,9 @@ module Admin
|
||||||
|
|
||||||
params[:q][:created_at_lteq] = ca_cache
|
params[:q][:created_at_lteq] = ca_cache
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def ident_types
|
||||||
|
Contact::Ident.types
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -152,9 +152,6 @@ class EppController < ApplicationController
|
||||||
code: '1',
|
code: '1',
|
||||||
msg: 'handle_errors was executed when there were actually no errors'
|
msg: 'handle_errors was executed when there were actually no errors'
|
||||||
}
|
}
|
||||||
# rubocop:disable Rails/Output
|
|
||||||
puts "FULL MESSAGE: #{obj.errors.full_messages} #{obj.errors.inspect}" if Rails.env.test?
|
|
||||||
# rubocop: enable Rails/Output
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@errors.uniq!
|
@errors.uniq!
|
||||||
|
|
|
@ -2,6 +2,7 @@ class Registrar
|
||||||
class ContactsController < DeppController
|
class ContactsController < DeppController
|
||||||
before_action :init_epp_contact
|
before_action :init_epp_contact
|
||||||
helper_method :address_processing?
|
helper_method :address_processing?
|
||||||
|
helper_method :ident_types
|
||||||
|
|
||||||
def index
|
def index
|
||||||
authorize! :view, Depp::Contact
|
authorize! :view, Depp::Contact
|
||||||
|
@ -140,5 +141,9 @@ class Registrar
|
||||||
def address_processing?
|
def address_processing?
|
||||||
Contact.address_processing?
|
Contact.address_processing?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def ident_types
|
||||||
|
Contact::Ident.types
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,6 +11,12 @@ module EppErrors
|
||||||
epp_errors << collect_child_errors(attr)
|
epp_errors << collect_child_errors(attr)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.class.reflect_on_aggregation(attr)
|
||||||
|
aggregation = send(attr)
|
||||||
|
epp_errors << collect_aggregation_errors(aggregation)
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
epp_errors << collect_parent_errors(attr, errors)
|
epp_errors << collect_parent_errors(attr, errors)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -46,6 +52,31 @@ module EppErrors
|
||||||
epp_errors
|
epp_errors
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def collect_aggregation_errors(aggregation)
|
||||||
|
epp_errors = []
|
||||||
|
|
||||||
|
aggregation.errors.details.each do |attr, error_details|
|
||||||
|
error_details.each do |error_detail|
|
||||||
|
aggregation.class.epp_code_map.each do |epp_code, attr_to_error|
|
||||||
|
epp_code_found = attr_to_error.any? { |i| i == [attr, error_detail[:error]] }
|
||||||
|
|
||||||
|
next unless epp_code_found
|
||||||
|
|
||||||
|
message = aggregation.errors.generate_message(attr, error_detail[:error], error_detail)
|
||||||
|
message = aggregation.errors.full_message(attr, message)
|
||||||
|
|
||||||
|
if attr != :base
|
||||||
|
message = "#{aggregation.model_name.human} #{message.camelize(:lower)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
epp_errors << { code: epp_code, msg: message }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
epp_errors
|
||||||
|
end
|
||||||
|
|
||||||
def find_epp_code_and_value(msg)
|
def find_epp_code_and_value(msg)
|
||||||
epp_code_map.each do |code, values|
|
epp_code_map.each do |code, values|
|
||||||
values.each do |x|
|
values.each do |x|
|
||||||
|
|
|
@ -19,27 +19,22 @@ class Contact < ActiveRecord::Base
|
||||||
|
|
||||||
accepts_nested_attributes_for :legal_documents
|
accepts_nested_attributes_for :legal_documents
|
||||||
|
|
||||||
validates :name, :phone, :email, :ident, :ident_type, presence: true
|
validates :name, :email, presence: true
|
||||||
validates :street, :city, :zip, :country_code, presence: true, if: 'self.class.address_processing?'
|
validates :street, :city, :zip, :country_code, presence: true, if: 'self.class.address_processing?'
|
||||||
|
|
||||||
validates :phone, format: /\+[0-9]{1,3}\.[0-9]{1,14}?/, phone: true
|
validates :phone, presence: true, e164: true, phone: true
|
||||||
|
|
||||||
validates :email, format: /@/
|
validates :email, format: /@/
|
||||||
validates :email, email_format: { message: :invalid }, if: proc { |c| c.email_changed? }
|
validates :email, email_format: { message: :invalid }, if: proc { |c| c.email_changed? }
|
||||||
validates :ident,
|
|
||||||
format: { with: /\d{4}-\d{2}-\d{2}/, message: :invalid_birthday_format },
|
|
||||||
if: proc { |c| c.ident_type == 'birthday' }
|
|
||||||
validates :ident_country_code, presence: true, if: proc { |c| %w(org priv).include? c.ident_type }, on: :create
|
|
||||||
validates :code,
|
validates :code,
|
||||||
uniqueness: { message: :epp_id_taken },
|
uniqueness: { message: :epp_id_taken },
|
||||||
format: { with: /\A[\w\-\:\.\_]*\z/i, message: :invalid },
|
format: { with: /\A[\w\-\:\.\_]*\z/i, message: :invalid },
|
||||||
length: { maximum: 100, message: :too_long_contact_code }
|
length: { maximum: 100, message: :too_long_contact_code }
|
||||||
|
validates_associated :identifier
|
||||||
|
|
||||||
validate :val_ident_type
|
|
||||||
validate :val_ident_valid_format?
|
|
||||||
validate :validate_html
|
validate :validate_html
|
||||||
validate :validate_country_code
|
validate :validate_country_code
|
||||||
validate :validate_ident_country_code
|
|
||||||
|
|
||||||
after_initialize do
|
after_initialize do
|
||||||
self.status_notes = {} if status_notes.nil?
|
self.status_notes = {} if status_notes.nil?
|
||||||
|
@ -49,8 +44,15 @@ class Contact < ActiveRecord::Base
|
||||||
before_validation :to_upcase_country_code
|
before_validation :to_upcase_country_code
|
||||||
before_validation :strip_email
|
before_validation :strip_email
|
||||||
before_create :generate_auth_info
|
before_create :generate_auth_info
|
||||||
|
|
||||||
before_update :manage_emails
|
before_update :manage_emails
|
||||||
|
|
||||||
|
composed_of :identifier,
|
||||||
|
class_name: 'Contact::Ident',
|
||||||
|
constructor: proc { |code, type, country_code| Contact::Ident.new(code: code,
|
||||||
|
type: type,
|
||||||
|
country_code: country_code) },
|
||||||
|
mapping: [%w[ident code], %w[ident_type type], %w[ident_country_code country_code]]
|
||||||
|
|
||||||
def manage_emails
|
def manage_emails
|
||||||
return nil unless email_changed?
|
return nil unless email_changed?
|
||||||
return nil unless deliver_emails == true
|
return nil unless deliver_emails == true
|
||||||
|
@ -76,12 +78,6 @@ class Contact < ActiveRecord::Base
|
||||||
BIRTHDAY = 'birthday'.freeze
|
BIRTHDAY = 'birthday'.freeze
|
||||||
PASSPORT = 'passport'
|
PASSPORT = 'passport'
|
||||||
|
|
||||||
IDENT_TYPES = [
|
|
||||||
ORG, # Company registry code (or similar)
|
|
||||||
PRIV, # National idendtification number
|
|
||||||
BIRTHDAY # Birthday date
|
|
||||||
]
|
|
||||||
|
|
||||||
attr_accessor :deliver_emails
|
attr_accessor :deliver_emails
|
||||||
attr_accessor :domain_transfer # hack but solves problem faster
|
attr_accessor :domain_transfer # hack but solves problem faster
|
||||||
|
|
||||||
|
@ -219,10 +215,6 @@ class Contact < ActiveRecord::Base
|
||||||
STDOUT << "#{Time.zone.now.utc} - Successfully destroyed #{counter} orphaned contacts\n" unless Rails.env.test?
|
STDOUT << "#{Time.zone.now.utc} - Successfully destroyed #{counter} orphaned contacts\n" unless Rails.env.test?
|
||||||
end
|
end
|
||||||
|
|
||||||
def privs
|
|
||||||
where("ident_type = '#{PRIV}'")
|
|
||||||
end
|
|
||||||
|
|
||||||
def admin_statuses
|
def admin_statuses
|
||||||
[
|
[
|
||||||
SERVER_UPDATE_PROHIBITED,
|
SERVER_UPDATE_PROHIBITED,
|
||||||
|
@ -299,28 +291,6 @@ class Contact < ActiveRecord::Base
|
||||||
name || '[no name]'
|
name || '[no name]'
|
||||||
end
|
end
|
||||||
|
|
||||||
def val_ident_type
|
|
||||||
errors.add(:ident_type, :epp_ident_type_invalid, code: code) if !%w(org priv birthday).include?(ident_type)
|
|
||||||
end
|
|
||||||
|
|
||||||
def val_ident_valid_format?
|
|
||||||
case ident_country_code
|
|
||||||
when 'EE'.freeze
|
|
||||||
err_msg = "invalid_EE_identity_format#{"_update" if id}".to_sym
|
|
||||||
case ident_type
|
|
||||||
when 'priv'.freeze
|
|
||||||
errors.add(:ident, err_msg) unless Isikukood.new(ident).valid?
|
|
||||||
when 'org'.freeze
|
|
||||||
# !%w(1 7 8 9).freeze.include?(ident.first) ||
|
|
||||||
if ident.size != 8 || !(ident =~/\A[0-9]{8}\z/)
|
|
||||||
errors.add(:ident, err_msg)
|
|
||||||
end
|
|
||||||
when BIRTHDAY
|
|
||||||
errors.add(:ident, err_msg) if id.blank? # only for create action right now. Later for all of them
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate_html
|
def validate_html
|
||||||
self.class.columns.each do |column|
|
self.class.columns.each do |column|
|
||||||
next unless column.type == :string
|
next unless column.type == :string
|
||||||
|
@ -334,7 +304,6 @@ class Contact < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def org?
|
def org?
|
||||||
ident_type == ORG
|
ident_type == ORG
|
||||||
end
|
end
|
||||||
|
@ -344,10 +313,6 @@ class Contact < ActiveRecord::Base
|
||||||
!org?
|
!org?
|
||||||
end
|
end
|
||||||
|
|
||||||
def birthday?
|
|
||||||
ident_type == BIRTHDAY
|
|
||||||
end
|
|
||||||
|
|
||||||
def generate_auth_info
|
def generate_auth_info
|
||||||
return if @generate_auth_info_disabled
|
return if @generate_auth_info_disabled
|
||||||
return if auth_info.present?
|
return if auth_info.present?
|
||||||
|
@ -424,10 +389,6 @@ class Contact < ActiveRecord::Base
|
||||||
errors.add(:country_code, :invalid) unless Country.new(country_code)
|
errors.add(:country_code, :invalid) unless Country.new(country_code)
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_ident_country_code
|
|
||||||
errors.add(:ident, :invalid_country_code) unless Country.new(ident_country_code)
|
|
||||||
end
|
|
||||||
|
|
||||||
def related_domain_descriptions
|
def related_domain_descriptions
|
||||||
ActiveSupport::Deprecation.warn('Use #domain_names_with_roles')
|
ActiveSupport::Deprecation.warn('Use #domain_names_with_roles')
|
||||||
|
|
||||||
|
@ -572,7 +533,7 @@ class Contact < ActiveRecord::Base
|
||||||
return if changes.slice(*(self.class.column_names - ["updated_at", "created_at", "statuses", "status_notes"])).empty?
|
return if changes.slice(*(self.class.column_names - ["updated_at", "created_at", "statuses", "status_notes"])).empty?
|
||||||
|
|
||||||
names = related_domain_descriptions.keys
|
names = related_domain_descriptions.keys
|
||||||
UpdateWhoisRecordJob.enqueue(names, :domain) if names.present?
|
UpdateWhoisRecordJob.enqueue(names, 'domain') if names.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def children_log
|
def children_log
|
||||||
|
|
74
app/models/contact/ident.rb
Normal file
74
app/models/contact/ident.rb
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
class Contact::Ident
|
||||||
|
include ActiveModel::Model
|
||||||
|
|
||||||
|
attr_accessor :code
|
||||||
|
attr_accessor :type
|
||||||
|
attr_accessor :country_code
|
||||||
|
|
||||||
|
validates :code, presence: true
|
||||||
|
validates :code, national_id: true, if: :national_id?
|
||||||
|
validates :code, reg_no: true, if: :reg_no?
|
||||||
|
validates :code, iso8601: { date_only: true }, if: :birthday?
|
||||||
|
|
||||||
|
validates :type, presence: true, inclusion: { in: proc { types } }
|
||||||
|
validates :country_code, presence: true, iso31661_alpha2: true
|
||||||
|
validates_with MismatchValidator
|
||||||
|
|
||||||
|
def self.epp_code_map
|
||||||
|
{
|
||||||
|
'2003' => [
|
||||||
|
[:code, :blank],
|
||||||
|
[:type, :blank],
|
||||||
|
[:country_code, :blank]
|
||||||
|
],
|
||||||
|
'2005' => [
|
||||||
|
[:base, :mismatch],
|
||||||
|
[:code, :invalid_national_id],
|
||||||
|
[:code, :invalid_reg_no],
|
||||||
|
[:code, :invalid_iso8601_date],
|
||||||
|
[:country_code, :invalid_iso31661_alpha2]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.types
|
||||||
|
%w[org priv birthday]
|
||||||
|
end
|
||||||
|
|
||||||
|
def marked_for_destruction?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def birthday?
|
||||||
|
type == 'birthday'
|
||||||
|
end
|
||||||
|
|
||||||
|
def national_id?
|
||||||
|
type == 'priv'
|
||||||
|
end
|
||||||
|
|
||||||
|
def reg_no?
|
||||||
|
type == 'org'
|
||||||
|
end
|
||||||
|
|
||||||
|
def country
|
||||||
|
Country.new(country_code)
|
||||||
|
end
|
||||||
|
|
||||||
|
def ==(other_ident)
|
||||||
|
if other_ident.is_a?(self.class)
|
||||||
|
(code == other_ident.code) &&
|
||||||
|
(type == other_ident.type) &&
|
||||||
|
(country_code == other_ident.country_code)
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# https://github.com/rails/rails/issues/1513
|
||||||
|
def validation_context=(_value)
|
||||||
|
;
|
||||||
|
end
|
||||||
|
end
|
|
@ -109,7 +109,7 @@ class Epp::Contact < Contact
|
||||||
end
|
end
|
||||||
delegate :ident_attr_valid?, to: :class
|
delegate :ident_attr_valid?, to: :class
|
||||||
|
|
||||||
def epp_code_map # rubocop:disable Metrics/MethodLength
|
def epp_code_map
|
||||||
{
|
{
|
||||||
'2003' => [ # Required parameter missing
|
'2003' => [ # Required parameter missing
|
||||||
[:name, :blank],
|
[:name, :blank],
|
||||||
|
@ -124,31 +124,19 @@ class Epp::Contact < Contact
|
||||||
[:name, :invalid],
|
[:name, :invalid],
|
||||||
[:phone, :invalid],
|
[:phone, :invalid],
|
||||||
[:email, :invalid],
|
[:email, :invalid],
|
||||||
[:ident, :invalid],
|
|
||||||
[:ident, :invalid_EE_identity_format],
|
|
||||||
[:ident, :invalid_EE_identity_format_update],
|
|
||||||
[:ident, :invalid_birthday_format],
|
|
||||||
[:ident, :invalid_country_code],
|
|
||||||
[:country_code, :invalid],
|
[:country_code, :invalid],
|
||||||
[:ident_type, :missing],
|
|
||||||
[:code, :invalid],
|
[:code, :invalid],
|
||||||
[:code, :too_long_contact_code]
|
[:code, :too_long_contact_code]
|
||||||
],
|
],
|
||||||
'2302' => [ # Object exists
|
'2302' => [ # Object exists
|
||||||
[:code, :epp_id_taken]
|
[:code, :epp_id_taken]
|
||||||
],
|
],
|
||||||
'2304' => [ # Object status prohibits operation
|
|
||||||
[:ident_type, :epp_ident_type_invalid, { value: { obj: 'code', val: code}, interpolation: {code: code}}]
|
|
||||||
],
|
|
||||||
'2305' => [ # Association exists
|
'2305' => [ # Association exists
|
||||||
[:domains, :exist]
|
[:domains, :exist]
|
||||||
],
|
|
||||||
'2306' => [ # Parameter policy error
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
# rubocop:disable Metrics/AbcSize
|
|
||||||
def update_attributes(frame, current_user)
|
def update_attributes(frame, current_user)
|
||||||
return super if frame.blank?
|
return super if frame.blank?
|
||||||
at = {}.with_indifferent_access
|
at = {}.with_indifferent_access
|
||||||
|
@ -158,9 +146,6 @@ class Epp::Contact < Contact
|
||||||
at[:statuses] = statuses - statuses_attrs(frame.css('rem'), 'rem') + statuses_attrs(frame.css('add'), 'add')
|
at[:statuses] = statuses - statuses_attrs(frame.css('rem'), 'rem') + statuses_attrs(frame.css('add'), 'add')
|
||||||
end
|
end
|
||||||
|
|
||||||
# legal_frame = frame.css('legalDocument').first
|
|
||||||
# at[:legal_documents_attributes] = self.class.legal_document_attrs(legal_frame)
|
|
||||||
|
|
||||||
if doc = attach_legal_document(Epp::Domain.parse_legal_document_from_frame(frame))
|
if doc = attach_legal_document(Epp::Domain.parse_legal_document_from_frame(frame))
|
||||||
frame.css("legalDocument").first.content = doc.path if doc && doc.persisted?
|
frame.css("legalDocument").first.content = doc.path if doc && doc.persisted?
|
||||||
self.legal_document_id = doc.id
|
self.legal_document_id = doc.id
|
||||||
|
@ -168,29 +153,28 @@ class Epp::Contact < Contact
|
||||||
|
|
||||||
self.deliver_emails = true # turn on email delivery for epp
|
self.deliver_emails = true # turn on email delivery for epp
|
||||||
|
|
||||||
|
ident_frame = frame.css('ident').first
|
||||||
|
|
||||||
# allow to update ident code for legacy contacts
|
# https://github.com/internetee/registry/issues/576
|
||||||
if frame.css('ident').first
|
if ident_frame
|
||||||
self.ident_updated_at ||= Time.zone.now # not in use
|
if identifier.valid?
|
||||||
ident_frame = frame.css('ident').first
|
submitted_ident = Ident.new(code: ident_frame.text,
|
||||||
|
type: ident_frame.attr('type'),
|
||||||
|
country_code: ident_frame.attr('cc'))
|
||||||
|
|
||||||
if ident_frame && ident_attr_valid?(ident_frame)
|
report_valid_ident_error if submitted_ident != identifier
|
||||||
org_priv = %w(org priv).freeze
|
|
||||||
if ident_country_code.blank? && org_priv.include?(ident_type) && org_priv.include?(ident_frame.attr('type'))
|
|
||||||
at.merge!(ident_country_code: ident_frame.attr('cc'), ident_type: ident_frame.attr('type'))
|
|
||||||
elsif ident_type == "birthday" && !ident[/\A\d{4}-\d{2}-\d{2}\z/] && (Date.parse(ident) rescue false)
|
|
||||||
at.merge!(ident: ident_frame.text)
|
|
||||||
at.merge!(ident_country_code: ident_frame.attr('cc')) if ident_frame.attr('cc').present?
|
|
||||||
elsif ident_type == "birthday" && ident_country_code.blank?
|
|
||||||
at.merge!(ident_country_code: ident_frame.attr('cc'))
|
|
||||||
elsif ident_type.blank? && ident_country_code.blank?
|
|
||||||
at.merge!(ident_type: ident_frame.attr('type'))
|
|
||||||
at.merge!(ident_country_code: ident_frame.attr('cc')) if ident_frame.attr('cc').present?
|
|
||||||
else
|
|
||||||
throw :epp_error, {code: '2306', msg: I18n.t(:ident_update_error)}
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
throw :epp_error, {code: '2306', msg: I18n.t(:ident_update_error)}
|
ident_update_attempt = ident_frame.text.present? && (ident_frame.text != ident)
|
||||||
|
report_ident_update_error if ident_update_attempt
|
||||||
|
|
||||||
|
identifier = Ident.new(code: ident,
|
||||||
|
type: ident_frame.attr('type'),
|
||||||
|
country_code: ident_frame.attr('cc'))
|
||||||
|
|
||||||
|
identifier.validate
|
||||||
|
|
||||||
|
self.identifier = identifier
|
||||||
|
self.ident_updated_at ||= Time.zone.now
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -199,7 +183,6 @@ class Epp::Contact < Contact
|
||||||
|
|
||||||
super(at)
|
super(at)
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/AbcSize
|
|
||||||
|
|
||||||
def statuses_attrs(frame, action)
|
def statuses_attrs(frame, action)
|
||||||
status_list = status_list_from(frame)
|
status_list = status_list_from(frame)
|
||||||
|
@ -259,4 +242,13 @@ class Epp::Contact < Contact
|
||||||
self.legal_document_id = doc.id
|
self.legal_document_id = doc.id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def report_valid_ident_error
|
||||||
|
throw :epp_error, { code: '2308', msg: I18n.t('epp.contacts.errors.valid_ident') }
|
||||||
|
end
|
||||||
|
|
||||||
|
def report_ident_update_error
|
||||||
|
throw :epp_error, { code: '2308', msg: I18n.t('epp.contacts.errors.ident_update') }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
22
app/models/epp/response.rb
Normal file
22
app/models/epp/response.rb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
module EPP
|
||||||
|
class Response
|
||||||
|
attr_accessor :results
|
||||||
|
|
||||||
|
def self.from_xml(xml)
|
||||||
|
xml_doc = Nokogiri::XML(xml)
|
||||||
|
response = new
|
||||||
|
|
||||||
|
result_elements = xml_doc.css('result')
|
||||||
|
|
||||||
|
result_elements.each do |result_element|
|
||||||
|
response.results << Result.new(result_element[:code].to_s, result_element.text.strip)
|
||||||
|
end
|
||||||
|
|
||||||
|
response
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@results = []
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
28
app/models/epp/response/result.rb
Normal file
28
app/models/epp/response/result.rb
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
module EPP
|
||||||
|
class Response
|
||||||
|
class Result
|
||||||
|
CODE_TO_TYPE = {
|
||||||
|
'1000' => :success,
|
||||||
|
'1001' => :success_pending,
|
||||||
|
'1300' => :success_empty_queue,
|
||||||
|
'1301' => :success_dequeue,
|
||||||
|
'2001' => :syntax_error,
|
||||||
|
'2003' => :required_param_missing,
|
||||||
|
'2005' => :param_syntax_error,
|
||||||
|
'2308' => :data_management_policy_violation
|
||||||
|
}
|
||||||
|
|
||||||
|
attr_accessor :code
|
||||||
|
attr_accessor :message
|
||||||
|
|
||||||
|
def initialize(code, message)
|
||||||
|
@code = code
|
||||||
|
@message = message
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.codes
|
||||||
|
CODE_TO_TYPE
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -9,7 +9,6 @@ class Registrar < ActiveRecord::Base
|
||||||
has_many :accounts
|
has_many :accounts
|
||||||
has_many :nameservers, through: :domains
|
has_many :nameservers, through: :domains
|
||||||
has_many :whois_records
|
has_many :whois_records
|
||||||
has_many :priv_contacts, -> { privs }, class_name: 'Contact'
|
|
||||||
has_many :white_ips, dependent: :destroy
|
has_many :white_ips, dependent: :destroy
|
||||||
|
|
||||||
delegate :balance, to: :cash_account, allow_nil: true
|
delegate :balance, to: :cash_account, allow_nil: true
|
||||||
|
|
20
app/validators/contact/ident/mismatch_validator.rb
Normal file
20
app/validators/contact/ident/mismatch_validator.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
class Contact::Ident::MismatchValidator < ActiveModel::Validator
|
||||||
|
Mismatch = Struct.new(:type, :country)
|
||||||
|
|
||||||
|
def self.mismatches
|
||||||
|
[
|
||||||
|
Mismatch.new('birthday', Country.new('EE')),
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate(record)
|
||||||
|
record.errors.add(:base, :mismatch, type: record.type, country: record.country) if mismatched?(record)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def mismatched?(record)
|
||||||
|
mismatch = Mismatch.new(record.type, record.country)
|
||||||
|
self.class.mismatches.include?(mismatch)
|
||||||
|
end
|
||||||
|
end
|
22
app/validators/contact/ident/national_id_validator.rb
Normal file
22
app/validators/contact/ident/national_id_validator.rb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
class Contact::Ident::NationalIdValidator < ActiveModel::EachValidator
|
||||||
|
def self.country_specific_validations
|
||||||
|
{
|
||||||
|
Country.new('EE') => proc { |code| Isikukood.new(code).valid? },
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_each(record, attribute, value)
|
||||||
|
validation = validation_for(record.country)
|
||||||
|
|
||||||
|
return unless validation
|
||||||
|
|
||||||
|
valid = validation.call(value)
|
||||||
|
record.errors.add(attribute, :invalid_national_id, country: record.country) unless valid
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def validation_for(country)
|
||||||
|
self.class.country_specific_validations[country]
|
||||||
|
end
|
||||||
|
end
|
21
app/validators/contact/ident/reg_no_validator.rb
Normal file
21
app/validators/contact/ident/reg_no_validator.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
class Contact::Ident::RegNoValidator < ActiveModel::EachValidator
|
||||||
|
def self.country_specific_formats
|
||||||
|
{
|
||||||
|
Country.new('EE') => /\A[0-9]{8}\z/,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_each(record, attribute, value)
|
||||||
|
format = format_for(record.country)
|
||||||
|
|
||||||
|
return unless format
|
||||||
|
|
||||||
|
record.errors.add(attribute, :invalid_reg_no, country: record.country) unless value =~ format
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def format_for(country)
|
||||||
|
self.class.country_specific_formats[country]
|
||||||
|
end
|
||||||
|
end
|
|
@ -19,7 +19,7 @@
|
||||||
.col-md-3
|
.col-md-3
|
||||||
.form-group
|
.form-group
|
||||||
= label_tag t(:ident_type)
|
= label_tag t(:ident_type)
|
||||||
= select_tag '[q][ident_type_eq]', options_for_select(Contact::IDENT_TYPES, params[:q][:ident_type_eq]), { include_blank: true, placeholder: t(:choose), class: 'form-control selectize' }
|
= select_tag '[q][ident_type_eq]', options_for_select(ident_types, params[:q][:ident_type_eq]), { include_blank: true, placeholder: t(:choose), class: 'form-control selectize' }
|
||||||
.row
|
.row
|
||||||
.col-md-3
|
.col-md-3
|
||||||
.form-group
|
.form-group
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
.row
|
.row
|
||||||
.col-md-12
|
.col-md-12
|
||||||
.table-responsive
|
.table-responsive
|
||||||
%table.table.table-hover.table-bordered.table-condensed
|
%table.table.table-hover.table-bordered.table-condensed.contacts
|
||||||
%thead
|
%thead
|
||||||
%tr
|
%tr
|
||||||
%th{class: 'col-xs-2'}
|
%th{class: 'col-xs-2'}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
.col-md-3
|
.col-md-3
|
||||||
.form-group
|
.form-group
|
||||||
= label_tag t(:ident_type)
|
= label_tag t(:ident_type)
|
||||||
= select_tag '[q][ident_type_eq]', options_for_select(Contact::IDENT_TYPES, params[:q][:ident_type_eq]), { include_blank: true, placeholder: t(:choose), class: 'form-control selectize' }
|
= select_tag '[q][ident_type_eq]', options_for_select(ident_types, params[:q][:ident_type_eq]), { include_blank: true, placeholder: t(:choose), class: 'form-control selectize' }
|
||||||
.row
|
.row
|
||||||
.col-md-3
|
.col-md-3
|
||||||
.form-group
|
.form-group
|
||||||
|
@ -85,7 +85,7 @@
|
||||||
.row
|
.row
|
||||||
.col-md-12
|
.col-md-12
|
||||||
.table-responsive
|
.table-responsive
|
||||||
%table.table.table-hover.table-bordered.table-condensed
|
%table.table.table-hover.table-bordered.table-condensed.contacts
|
||||||
%thead
|
%thead
|
||||||
%tr
|
%tr
|
||||||
%th{class: 'col-xs-2'}
|
%th{class: 'col-xs-2'}
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
# Log all active model user errors
|
|
||||||
# rubocop: disable Lint/AssignmentInCondition
|
|
||||||
# rubocop: disable Style/SignalException
|
|
||||||
module ActiveModel
|
|
||||||
class Errors
|
|
||||||
def add(attribute, message = :invalid, options = {})
|
|
||||||
message = normalize_message(attribute, message, options)
|
|
||||||
if exception = options[:strict]
|
|
||||||
exception = ActiveModel::StrictValidationFailed if exception == true
|
|
||||||
raise exception, full_message(attribute, message)
|
|
||||||
end
|
|
||||||
|
|
||||||
# CUSTOM logging
|
|
||||||
Rails.logger.info "USER MSG: ACTIVEMODEL: #{@base.try(:class)} [#{attribute}] #{message}" if message.present?
|
|
||||||
# END of CUSTOM logging
|
|
||||||
|
|
||||||
self[attribute] << message
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,31 +0,0 @@
|
||||||
# Log all flash messages
|
|
||||||
# rubocop: disable Metrics/CyclomaticComplexity
|
|
||||||
# rubocop: disable Metrics/LineLength
|
|
||||||
module ActionDispatch
|
|
||||||
class Flash
|
|
||||||
# rubocop: disable Metrics/PerceivedComplexity
|
|
||||||
# rubocop: disable Style/MultilineOperationIndentation
|
|
||||||
def call(env)
|
|
||||||
@app.call(env)
|
|
||||||
ensure
|
|
||||||
session = Request::Session.find(env) || {}
|
|
||||||
flash_hash = env[KEY]
|
|
||||||
|
|
||||||
if flash_hash && (flash_hash.present? || session.key?('flash'))
|
|
||||||
session["flash"] = flash_hash.to_session_value
|
|
||||||
|
|
||||||
# EIS custom logging
|
|
||||||
Rails.logger.info "USER MSG: FLASH: #{session['flash']['flashes'].inspect}" if session['flash']
|
|
||||||
# END OF EIS custom logging
|
|
||||||
|
|
||||||
env[KEY] = flash_hash.dup
|
|
||||||
end
|
|
||||||
|
|
||||||
if (!session.respond_to?(:loaded?) || session.loaded?) && # (reset_session uses {}, which doesn't implement #loaded?)
|
|
||||||
session.key?('flash') && session['flash'].nil?
|
|
||||||
session.delete('flash')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -9,5 +9,20 @@ en:
|
||||||
models:
|
models:
|
||||||
contact:
|
contact:
|
||||||
attributes:
|
attributes:
|
||||||
|
code:
|
||||||
|
blank: "Required parameter missing - code"
|
||||||
|
too_long_contact_code: "Contact code is too long, max 100 characters"
|
||||||
|
name:
|
||||||
|
blank: "Required parameter missing - name"
|
||||||
|
phone:
|
||||||
|
blank: "Required parameter missing - phone"
|
||||||
|
invalid: "Phone nr is invalid"
|
||||||
|
email:
|
||||||
|
blank: "Required parameter missing - email"
|
||||||
|
invalid: "Email is invalid"
|
||||||
|
domains:
|
||||||
|
exist: 'Object association prohibits operation'
|
||||||
|
statuses:
|
||||||
|
not_uniq: 'not uniq'
|
||||||
country_code:
|
country_code:
|
||||||
invalid: Country code is not valid, should be in ISO_3166-1 alpha 2 format
|
invalid: Country code is not valid, should be in ISO_3166-1 alpha 2 format
|
||||||
|
|
|
@ -34,33 +34,6 @@ en:
|
||||||
activerecord:
|
activerecord:
|
||||||
errors:
|
errors:
|
||||||
models:
|
models:
|
||||||
contact:
|
|
||||||
attributes:
|
|
||||||
code:
|
|
||||||
blank: "Required parameter missing - code"
|
|
||||||
too_long_contact_code: "Contact code is too long, max 100 characters"
|
|
||||||
name:
|
|
||||||
blank: "Required parameter missing - name"
|
|
||||||
phone:
|
|
||||||
blank: "Required parameter missing - phone"
|
|
||||||
invalid: "Phone nr is invalid"
|
|
||||||
email:
|
|
||||||
blank: "Required parameter missing - email"
|
|
||||||
invalid: "Email is invalid"
|
|
||||||
ident:
|
|
||||||
blank: "Required parameter missing - ident"
|
|
||||||
invalid_EE_identity_format: "Ident not in valid Estonian identity format."
|
|
||||||
invalid_EE_identity_format_update: "Ident not in valid Estonian identity format. Please create new contact"
|
|
||||||
invalid_birthday_format: "Ident not in valid birthady format, should be YYYY-MM-DD"
|
|
||||||
invalid_country_code: "Ident country code is not valid, should be in ISO_3166-1 alpha 2 format"
|
|
||||||
ident_type:
|
|
||||||
ident_type_invalid: 'Ident type is invalid'
|
|
||||||
epp_ident_type_invalid: 'Object status prohibits operation: ident_type of contact %{code} is invalid'
|
|
||||||
domains:
|
|
||||||
exist: 'Object association prohibits operation'
|
|
||||||
statuses:
|
|
||||||
not_uniq: 'not uniq'
|
|
||||||
|
|
||||||
epp_domain: &epp_domain_ar_attributes
|
epp_domain: &epp_domain_ar_attributes
|
||||||
attributes:
|
attributes:
|
||||||
base:
|
base:
|
||||||
|
@ -262,6 +235,8 @@ en:
|
||||||
unimplemented_command: 'Unimplemented command'
|
unimplemented_command: 'Unimplemented command'
|
||||||
domain_exists_but_belongs_to_other_registrar: 'Domain exists but belongs to other registrar'
|
domain_exists_but_belongs_to_other_registrar: 'Domain exists but belongs to other registrar'
|
||||||
required_ident_attribute_missing: "Required ident attribute missing: %{key}"
|
required_ident_attribute_missing: "Required ident attribute missing: %{key}"
|
||||||
|
invalid_iso31661_alpha2: does not conform to ISO 3166-1 alpha-2 standard
|
||||||
|
invalid_iso8601_date: has invalid date format YYYY-MM-DD (ISO 8601)
|
||||||
|
|
||||||
code: 'Code'
|
code: 'Code'
|
||||||
action: 'Action'
|
action: 'Action'
|
||||||
|
@ -487,7 +462,6 @@ en:
|
||||||
crt_revoked: 'CRT (revoked)'
|
crt_revoked: 'CRT (revoked)'
|
||||||
contact_org_error: 'Parameter value policy error. Org must be blank'
|
contact_org_error: 'Parameter value policy error. Org must be blank'
|
||||||
contact_fax_error: 'Parameter value policy error. Fax must be blank'
|
contact_fax_error: 'Parameter value policy error. Fax must be blank'
|
||||||
ident_update_error: 'Parameter value policy error. Update of ident data not allowed [ident]'
|
|
||||||
invoices: 'Invoices'
|
invoices: 'Invoices'
|
||||||
no_such_user: 'No such user'
|
no_such_user: 'No such user'
|
||||||
phone_no: 'Phone number'
|
phone_no: 'Phone number'
|
||||||
|
|
|
@ -3,3 +3,11 @@ en:
|
||||||
contacts:
|
contacts:
|
||||||
completed: Command completed successfully
|
completed: Command completed successfully
|
||||||
completed_without_address: Command completed successfully; Postal address data discarded
|
completed_without_address: Command completed successfully; Postal address data discarded
|
||||||
|
|
||||||
|
errors:
|
||||||
|
valid_ident: >-
|
||||||
|
Ident update is not allowed.
|
||||||
|
Consider creating new contact object
|
||||||
|
ident_update: >-
|
||||||
|
Only ident type and country can be updated in case of invalid ident.
|
||||||
|
Please create new contact object to update ident code
|
||||||
|
|
11
config/locales/idents.yml
Normal file
11
config/locales/idents.yml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
en:
|
||||||
|
activemodel:
|
||||||
|
errors:
|
||||||
|
models:
|
||||||
|
contact/ident:
|
||||||
|
attributes:
|
||||||
|
base:
|
||||||
|
mismatch: Ident type "%{type}" is invalid for %{country}
|
||||||
|
code:
|
||||||
|
invalid_national_id: does not conform to national identification number format of %{country}
|
||||||
|
invalid_reg_no: does not conform to registration number format of %{country}
|
|
@ -36,7 +36,7 @@ More info: https://en.wikipedia.org/wiki/Latin_script_in_Unicode
|
||||||
<contact:email> 1 E-mail
|
<contact:email> 1 E-mail
|
||||||
<extension> 1
|
<extension> 1
|
||||||
<eis:extdata> 1 Attribute: xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd"
|
<eis:extdata> 1 Attribute: xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd"
|
||||||
<eis:ident> 1 Contact identificator
|
<eis:ident> 1 Identifier
|
||||||
Attribute: "type"
|
Attribute: "type"
|
||||||
"org" # Business registry code
|
"org" # Business registry code
|
||||||
"priv" # National identification number
|
"priv" # National identification number
|
||||||
|
@ -73,7 +73,7 @@ More info: https://en.wikipedia.org/wiki/Latin_script_in_Unicode
|
||||||
<contact:pw> 1 Contact password. Attribute: roid="String"
|
<contact:pw> 1 Contact password. Attribute: roid="String"
|
||||||
<extension> 0-1
|
<extension> 0-1
|
||||||
<eis:extdata> 0-1 Attribute: xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd"
|
<eis:extdata> 0-1 Attribute: xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd"
|
||||||
<eis:ident> 0-1 Contact identificator
|
<eis:ident> 0-1 Identifier
|
||||||
Attribute: "type"
|
Attribute: "type"
|
||||||
"org" # Business registry code
|
"org" # Business registry code
|
||||||
"priv" # National identification number
|
"priv" # National identification number
|
||||||
|
|
|
@ -1031,25 +1031,11 @@
|
||||||
<polygon fill="#0374bc" stroke="#0374bc" points="2896.54,-311.549 2886.9,-306.334 2891.56,-311.185 2886.57,-310.822 2886.57,-310.822 2886.57,-310.822 2891.56,-311.185 2886.24,-315.31 2896.54,-311.549 2896.54,-311.549"/>
|
<polygon fill="#0374bc" stroke="#0374bc" points="2896.54,-311.549 2886.9,-306.334 2891.56,-311.185 2886.57,-310.822 2886.57,-310.822 2886.57,-310.822 2891.56,-311.185 2886.24,-315.31 2896.54,-311.549 2896.54,-311.549"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- Registrar->Contact -->
|
<!-- Registrar->Contact -->
|
||||||
<g id="edge68" class="edge"><title>Registrar->Contact</title>
|
|
||||||
<path fill="none" stroke="#08d288" d="M1289.24,-522.039C1610.25,-522.115 3337.74,-519.996 3565.99,-466 3599.47,-458.082 3606.71,-451.045 3635.99,-433 3658.1,-419.38 3659.77,-410.424 3681.99,-397 3698.68,-386.919 3711.41,-395.371 3721.99,-379 3772.14,-301.446 3754.66,-355.133 3112.99,-325 3037.3,-321.445 2949.51,-315.411 2896.66,-311.57"/>
|
|
||||||
<ellipse fill="none" stroke="#08d288" cx="1285.04" cy="-522.038" rx="4" ry="4"/>
|
|
||||||
<polygon fill="#08d288" stroke="#08d288" points="2896.54,-311.561 2886.9,-306.344 2891.56,-311.197 2886.57,-310.832 2886.57,-310.832 2886.57,-310.832 2891.56,-311.197 2886.24,-315.32 2896.54,-311.561 2896.54,-311.561"/>
|
|
||||||
<text text-anchor="middle" x="3718.49" y="-411.3" font-family="Times,serif" font-size="14.00">priv_contacts</text>
|
|
||||||
</g>
|
|
||||||
<!-- Registrar->Contact -->
|
|
||||||
<g id="edge105" class="edge"><title>Registrar->Contact</title>
|
<g id="edge105" class="edge"><title>Registrar->Contact</title>
|
||||||
<path fill="none" stroke="#983d43" d="M1289.27,-522.186C1639.37,-523.21 3666.41,-525.142 3754.99,-433 3768.3,-419.16 3746.5,-345.108 3743.99,-343 3717.15,-320.429 3148.03,-326.627 3112.99,-325 3037.29,-321.484 2949.51,-315.438 2896.66,-311.584"/>
|
<path fill="none" stroke="#983d43" d="M1289.27,-522.186C1639.37,-523.21 3666.41,-525.142 3754.99,-433 3768.3,-419.16 3746.5,-345.108 3743.99,-343 3717.15,-320.429 3148.03,-326.627 3112.99,-325 3037.29,-321.484 2949.51,-315.438 2896.66,-311.584"/>
|
||||||
<ellipse fill="none" stroke="#983d43" cx="1285.07" cy="-522.173" rx="4" ry="4"/>
|
<ellipse fill="none" stroke="#983d43" cx="1285.07" cy="-522.173" rx="4" ry="4"/>
|
||||||
<polygon fill="#983d43" stroke="#983d43" points="2896.54,-311.576 2886.9,-306.356 2891.56,-311.21 2886.57,-310.844 2886.57,-310.844 2886.57,-310.844 2891.56,-311.21 2886.24,-315.332 2896.54,-311.576 2896.54,-311.576"/>
|
<polygon fill="#983d43" stroke="#983d43" points="2896.54,-311.576 2886.9,-306.356 2891.56,-311.21 2886.57,-310.844 2886.57,-310.844 2886.57,-310.844 2891.56,-311.21 2886.24,-315.332 2896.54,-311.576 2896.54,-311.576"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- Registrar->Contact -->
|
|
||||||
<g id="edge112" class="edge"><title>Registrar->Contact</title>
|
|
||||||
<path fill="none" stroke="#aa3e5f" d="M1289.02,-521.999C1518.6,-521.522 2478.68,-514.494 3260.99,-433 3260.99,-433 3649.99,-379 3649.99,-379 3710.03,-310.049 3826.1,-359.903 3112.99,-325 3037.3,-321.295 2949.51,-315.304 2896.66,-311.513"/>
|
|
||||||
<ellipse fill="none" stroke="#aa3e5f" cx="1284.84" cy="-522.006" rx="4" ry="4"/>
|
|
||||||
<polygon fill="#aa3e5f" stroke="#aa3e5f" points="2896.55,-311.504 2886.89,-306.297 2891.56,-311.145 2886.57,-310.785 2886.57,-310.785 2886.57,-310.785 2891.56,-311.145 2886.25,-315.273 2896.55,-311.504 2896.55,-311.504"/>
|
|
||||||
<text text-anchor="middle" x="3555.49" y="-411.3" font-family="Times,serif" font-size="14.00">priv_contacts</text>
|
|
||||||
</g>
|
|
||||||
<!-- Registrar->Domain -->
|
<!-- Registrar->Domain -->
|
||||||
<g id="edge60" class="edge"><title>Registrar->Domain</title>
|
<g id="edge60" class="edge"><title>Registrar->Domain</title>
|
||||||
<path fill="none" stroke="#a7f439" d="M1285.22,-514.145C1410.96,-494.146 1752.36,-441.557 1878.45,-422.782"/>
|
<path fill="none" stroke="#a7f439" d="M1285.22,-514.145C1410.96,-494.146 1752.36,-441.557 1878.45,-422.782"/>
|
||||||
|
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 127 KiB |
|
@ -1643,25 +1643,11 @@
|
||||||
<polygon fill="#257f99" stroke="#257f99" points="3166.6,-1436.81 3164.86,-1425.98 3163.85,-1432.63 3161.1,-1428.45 3161.1,-1428.45 3161.1,-1428.45 3163.85,-1432.63 3157.34,-1430.93 3166.6,-1436.81 3166.6,-1436.81"/>
|
<polygon fill="#257f99" stroke="#257f99" points="3166.6,-1436.81 3164.86,-1425.98 3163.85,-1432.63 3161.1,-1428.45 3161.1,-1428.45 3161.1,-1428.45 3163.85,-1432.63 3157.34,-1430.93 3166.6,-1436.81 3166.6,-1436.81"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- Registrar->Contact -->
|
<!-- Registrar->Contact -->
|
||||||
<g id="edge68" class="edge"><title>Registrar->Contact</title>
|
|
||||||
<path fill="none" stroke="#625a51" d="M1737.79,-2486.74C2105.37,-2477.42 3671.93,-2427.41 3783,-2250 3886.64,-2084.47 3711.19,-1968.76 3829,-1813 3841.99,-1795.82 3861.92,-1812.84 3874,-1795 3894.81,-1764.27 3899.79,-1654.68 3874,-1628 3833.13,-1585.71 3397.45,-1636.61 3345,-1610 3270.62,-1572.26 3210.61,-1502.97 3166.63,-1436.95"/>
|
|
||||||
<ellipse fill="none" stroke="#625a51" cx="1733.59" cy="-2486.84" rx="4" ry="4"/>
|
|
||||||
<polygon fill="#625a51" stroke="#625a51" points="3166.57,-1436.86 3164.84,-1426.03 3163.82,-1432.68 3161.08,-1428.5 3161.08,-1428.5 3161.08,-1428.5 3163.82,-1432.68 3157.32,-1430.98 3166.57,-1436.86 3166.57,-1436.86"/>
|
|
||||||
<text text-anchor="middle" x="3865.5" y="-2027.8" font-family="Times,serif" font-size="14.00">priv_contacts</text>
|
|
||||||
</g>
|
|
||||||
<!-- Registrar->Contact -->
|
|
||||||
<g id="edge105" class="edge"><title>Registrar->Contact</title>
|
<g id="edge105" class="edge"><title>Registrar->Contact</title>
|
||||||
<path fill="none" stroke="#84dd57" d="M1737.74,-2486.28C2114.24,-2474.64 3753.89,-2414.71 3902,-2250 3948.21,-2198.61 3944.87,-1676.88 3896,-1628 3852.69,-1584.68 3399.64,-1637.68 3345,-1610 3270.59,-1572.31 3210.58,-1503.03 3166.61,-1437"/>
|
<path fill="none" stroke="#84dd57" d="M1737.74,-2486.28C2114.24,-2474.64 3753.89,-2414.71 3902,-2250 3948.21,-2198.61 3944.87,-1676.88 3896,-1628 3852.69,-1584.68 3399.64,-1637.68 3345,-1610 3270.59,-1572.31 3210.58,-1503.03 3166.61,-1437"/>
|
||||||
<ellipse fill="none" stroke="#84dd57" cx="1733.61" cy="-2486.41" rx="4" ry="4"/>
|
<ellipse fill="none" stroke="#84dd57" cx="1733.61" cy="-2486.41" rx="4" ry="4"/>
|
||||||
<polygon fill="#84dd57" stroke="#84dd57" points="3166.55,-1436.91 3164.81,-1426.08 3163.8,-1432.73 3161.05,-1428.55 3161.05,-1428.55 3161.05,-1428.55 3163.8,-1432.73 3157.29,-1431.02 3166.55,-1436.91 3166.55,-1436.91"/>
|
<polygon fill="#84dd57" stroke="#84dd57" points="3166.55,-1436.91 3164.81,-1426.08 3163.8,-1432.73 3161.05,-1428.55 3161.05,-1428.55 3161.05,-1428.55 3163.8,-1432.73 3157.29,-1431.02 3166.55,-1436.91 3166.55,-1436.91"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- Registrar->Contact -->
|
|
||||||
<g id="edge112" class="edge"><title>Registrar->Contact</title>
|
|
||||||
<path fill="none" stroke="#eb888a" d="M1738.05,-2484.46C2024.22,-2468.39 3023.5,-2402.27 3298,-2250 3520.54,-2126.55 3443.92,-1933.63 3668,-1813 3697.56,-1797.09 3795.72,-1820.11 3818,-1795 3842.63,-1767.24 3843.74,-1654.74 3818,-1628 3781.52,-1590.11 3391.85,-1633.89 3345,-1610 3270.7,-1572.11 3210.7,-1502.8 3166.7,-1436.81"/>
|
|
||||||
<ellipse fill="none" stroke="#eb888a" cx="1733.79" cy="-2484.7" rx="4" ry="4"/>
|
|
||||||
<polygon fill="#eb888a" stroke="#eb888a" points="3166.64,-1436.72 3164.91,-1425.89 3163.9,-1432.54 3161.15,-1428.37 3161.15,-1428.37 3161.15,-1428.37 3163.9,-1432.54 3157.39,-1430.84 3166.64,-1436.72 3166.64,-1436.72"/>
|
|
||||||
<text text-anchor="middle" x="3704.5" y="-2027.8" font-family="Times,serif" font-size="14.00">priv_contacts</text>
|
|
||||||
</g>
|
|
||||||
<!-- Registrar->Domain -->
|
<!-- Registrar->Domain -->
|
||||||
<g id="edge60" class="edge"><title>Registrar->Domain</title>
|
<g id="edge60" class="edge"><title>Registrar->Domain</title>
|
||||||
<path fill="none" stroke="#6a2f42" d="M1734.92,-2400.64C1792.79,-2335.05 1874.64,-2244.16 1943.33,-2169.11"/>
|
<path fill="none" stroke="#6a2f42" d="M1734.92,-2400.64C1792.79,-2335.05 1874.64,-2244.16 1943.33,-2169.11"/>
|
||||||
|
|
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 232 KiB |
|
@ -174,6 +174,8 @@ namespace :dev do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Setting.api_ip_whitelist_enabled = false
|
||||||
|
Setting.address_processing = false
|
||||||
Setting.registrar_ip_whitelist_enabled = false
|
Setting.registrar_ip_whitelist_enabled = false
|
||||||
|
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
|
|
12
lib/validators/e164_validator.rb
Normal file
12
lib/validators/e164_validator.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
class E164Validator < ActiveModel::EachValidator
|
||||||
|
def validate_each(record, attribute, _value)
|
||||||
|
length_validator = ActiveModel::Validations::
|
||||||
|
LengthValidator.new(maximum: 17, attributes: attribute)
|
||||||
|
length_validator.validate(record)
|
||||||
|
|
||||||
|
format_validator = ActiveModel::Validations::
|
||||||
|
FormatValidator.new(with: /\+[0-9]{1,3}\.[0-9]{1,14}?/,
|
||||||
|
attributes: attribute)
|
||||||
|
format_validator.validate(record)
|
||||||
|
end
|
||||||
|
end
|
11
lib/validators/iso31661_alpha2_validator.rb
Normal file
11
lib/validators/iso31661_alpha2_validator.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
class Iso31661Alpha2Validator < ActiveModel::EachValidator
|
||||||
|
def validate_each(record, attribute, value)
|
||||||
|
record.errors.add(attribute, :invalid_iso31661_alpha2) unless valid_country_code?(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def valid_country_code?(country_code)
|
||||||
|
Country.new(country_code)
|
||||||
|
end
|
||||||
|
end
|
13
lib/validators/iso8601_validator.rb
Normal file
13
lib/validators/iso8601_validator.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
class Iso8601Validator < ActiveModel::EachValidator
|
||||||
|
def validate_each(record, attribute, value)
|
||||||
|
if options[:date_only]
|
||||||
|
record.errors.add(attribute, :invalid_iso8601_date) unless value =~ date_format
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def date_format
|
||||||
|
/\d{4}-\d{2}-\d{2}/
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,11 +2,11 @@ class PhoneValidator < ActiveModel::EachValidator
|
||||||
def validate_each(record, attribute, value)
|
def validate_each(record, attribute, value)
|
||||||
return if record.errors[:phone].any?
|
return if record.errors[:phone].any?
|
||||||
|
|
||||||
splitted_phone = value.split('.')
|
phone_parts = value.split('.')
|
||||||
country_code = splitted_phone.first
|
country_code = phone_parts.first
|
||||||
phone_number = splitted_phone.second
|
subscriber_no = phone_parts.second
|
||||||
|
|
||||||
if zeros_only?(country_code) || zeros_only?(phone_number)
|
if zeros_only?(country_code) || zeros_only?(subscriber_no)
|
||||||
record.errors.add(attribute, :invalid)
|
record.errors.add(attribute, :invalid)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
12
spec/features/admin/contacts/list_spec.rb
Normal file
12
spec/features/admin/contacts/list_spec.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.feature 'Contact list', settings: false do
|
||||||
|
background do
|
||||||
|
sign_in_to_admin_area
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is visible' do
|
||||||
|
visit admin_contacts_path
|
||||||
|
expect(page).to have_css('.contacts')
|
||||||
|
end
|
||||||
|
end
|
15
spec/features/registrar/contacts/list_spec.rb
Normal file
15
spec/features/registrar/contacts/list_spec.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.feature 'Contact list', settings: false do
|
||||||
|
given!(:registrar) { create(:registrar) }
|
||||||
|
given!(:contact) { create(:contact, registrar: registrar) }
|
||||||
|
|
||||||
|
background do
|
||||||
|
sign_in_to_registrar_area(user: create(:api_user_with_unlimited_balance, registrar: registrar))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is visible' do
|
||||||
|
visit registrar_contacts_path
|
||||||
|
expect(page).to have_css('.contacts')
|
||||||
|
end
|
||||||
|
end
|
29
spec/lib/validators/e164.rb
Normal file
29
spec/lib/validators/e164.rb
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# https://en.wikipedia.org/wiki/E.164
|
||||||
|
|
||||||
|
RSpec.shared_examples 'e164' do
|
||||||
|
describe 'validation' do
|
||||||
|
it 'rejects invalid format' do
|
||||||
|
model.send("#{attribute}=", '+.1')
|
||||||
|
model.validate
|
||||||
|
expect(model.errors).to be_added(attribute, :invalid)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects longer than max length' do
|
||||||
|
model.send("#{attribute}=", '1' * 18)
|
||||||
|
model.validate
|
||||||
|
expect(model.errors).to be_added(attribute, :too_long, count: 17)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'accepts valid format' do
|
||||||
|
model.send("#{attribute}=", '+123.4')
|
||||||
|
model.validate
|
||||||
|
expect(model.errors).to_not be_added(attribute, :invalid)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'accepts max length' do
|
||||||
|
model.send("#{attribute}=", '1' * 17)
|
||||||
|
model.validate
|
||||||
|
expect(model.errors).to_not be_added(attribute, :too_long, count: 17)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
17
spec/lib/validators/iso31661_alpha2.rb
Normal file
17
spec/lib/validators/iso31661_alpha2.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
|
||||||
|
|
||||||
|
RSpec.shared_examples 'iso31661_alpha2' do
|
||||||
|
describe 'validation' do
|
||||||
|
it 'rejects invalid' do
|
||||||
|
model.send("#{attribute}=", 'invalid')
|
||||||
|
model.validate
|
||||||
|
expect(model.errors).to be_added(attribute, :invalid_iso31661_alpha2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'accepts valid' do
|
||||||
|
model.send("#{attribute}=", 'US')
|
||||||
|
model.validate
|
||||||
|
expect(model.errors).to_not be_added(attribute, :invalid_iso31661_alpha2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
17
spec/lib/validators/iso8601.rb
Normal file
17
spec/lib/validators/iso8601.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# https://en.wikipedia.org/wiki/ISO_8601
|
||||||
|
|
||||||
|
RSpec.shared_examples 'iso8601' do
|
||||||
|
describe 'validation' do
|
||||||
|
it 'rejects invalid' do
|
||||||
|
model.send("#{attribute}=", '2010-07-0')
|
||||||
|
model.validate
|
||||||
|
expect(model.errors).to be_added(attribute, :invalid_iso8601_date)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'accepts valid' do
|
||||||
|
model.send("#{attribute}=", '2010-07-05')
|
||||||
|
model.validate
|
||||||
|
expect(model.errors).to_not be_added(attribute, :invalid_iso8601_date)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
33
spec/models/contact/contact_phone_spec.rb
Normal file
33
spec/models/contact/contact_phone_spec.rb
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
require 'lib/validators/e164'
|
||||||
|
|
||||||
|
RSpec.describe Contact do
|
||||||
|
let(:contact) { described_class.new }
|
||||||
|
|
||||||
|
describe 'phone', db: false do
|
||||||
|
it_behaves_like 'e164' do
|
||||||
|
let(:model) { contact }
|
||||||
|
let(:attribute) { :phone }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'phone validation', db: false do
|
||||||
|
it 'rejects absent' do
|
||||||
|
contact.phone = nil
|
||||||
|
contact.validate
|
||||||
|
expect(contact.errors).to be_added(:phone, :blank)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects all zeros in country code' do
|
||||||
|
contact.phone = '+000.1'
|
||||||
|
contact.validate
|
||||||
|
expect(contact.errors).to be_added(:phone, :invalid)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects all zeros in subscriber number' do
|
||||||
|
contact.phone = '+123.0'
|
||||||
|
contact.validate
|
||||||
|
expect(contact.errors).to be_added(:phone, :invalid)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
227
spec/models/contact/ident_spec.rb
Normal file
227
spec/models/contact/ident_spec.rb
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
require 'active_model'
|
||||||
|
require 'lib/validators/iso31661_alpha2'
|
||||||
|
require 'lib/validators/iso8601'
|
||||||
|
|
||||||
|
RSpec.describe Contact::Ident, db: false do
|
||||||
|
let(:ident) { described_class.new }
|
||||||
|
|
||||||
|
describe 'country code' do
|
||||||
|
it_behaves_like 'iso31661_alpha2' do
|
||||||
|
let(:model) { ident }
|
||||||
|
let(:attribute) { :country_code }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'code validation' do
|
||||||
|
it 'rejects absent' do
|
||||||
|
ident.code = nil
|
||||||
|
ident.validate
|
||||||
|
expect(ident.errors).to be_added(:code, :blank)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when type is :birthday' do
|
||||||
|
let(:ident) { described_class.new(type: 'birthday') }
|
||||||
|
|
||||||
|
it_behaves_like 'iso8601' do
|
||||||
|
let(:model) { ident }
|
||||||
|
let(:attribute) { :code }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when type is not :birthday' do
|
||||||
|
let(:ident) { described_class.new(type: 'priv') }
|
||||||
|
|
||||||
|
it 'accepts any' do
|
||||||
|
ident.code = '%123456789%'
|
||||||
|
ident.validate
|
||||||
|
expect(ident.errors).to_not include(:code)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when country code is EE' do
|
||||||
|
context 'when type is :priv' do
|
||||||
|
let(:ident) { described_class.new(country_code: 'EE', type: 'priv') }
|
||||||
|
|
||||||
|
it 'rejects invalid' do
|
||||||
|
ident.code = 'invalid'
|
||||||
|
ident.validate
|
||||||
|
expect(ident.errors).to be_added(:code, :invalid_national_id, country: 'Estonia')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'accepts valid' do
|
||||||
|
ident.code = '47101010033'
|
||||||
|
ident.validate
|
||||||
|
expect(ident.errors).to_not be_added(:code, :invalid_national_id, country: 'Estonia')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when ident type is :org' do
|
||||||
|
let(:ident) { described_class.new(country_code: 'EE', type: 'org') }
|
||||||
|
|
||||||
|
it 'rejects invalid' do
|
||||||
|
ident.code = '1' * 7
|
||||||
|
ident.validate
|
||||||
|
expect(ident.errors).to be_added(:code, :invalid_reg_no, country: 'Estonia')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'accepts valid length' do
|
||||||
|
ident.code = '1' * 8
|
||||||
|
ident.validate
|
||||||
|
expect(ident.errors).to_not be_added(:code, :invalid_reg_no, country: 'Estonia')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when ident country code is not EE' do
|
||||||
|
let(:ident) { described_class.new(country_code: 'US') }
|
||||||
|
|
||||||
|
it 'accepts any' do
|
||||||
|
ident.code = 'test-123456789'
|
||||||
|
ident.validate
|
||||||
|
expect(ident.errors).to_not include(:code)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'translates :invalid_national_id error message' do
|
||||||
|
expect(ident.errors.generate_message(:code, :invalid_national_id, country: 'Germany'))
|
||||||
|
.to eq('does not conform to national identification number format of Germany')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'translates :invalid_reg_no error message' do
|
||||||
|
expect(ident.errors.generate_message(:code, :invalid_reg_no, country: 'Germany'))
|
||||||
|
.to eq('does not conform to registration number format of Germany')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'type validation' do
|
||||||
|
before do
|
||||||
|
allow(described_class).to receive(:types).and_return(%w(valid))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects absent' do
|
||||||
|
ident.type = nil
|
||||||
|
ident.validate
|
||||||
|
expect(ident.errors).to be_added(:type, :blank)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects invalid' do
|
||||||
|
ident.type = 'invalid'
|
||||||
|
ident.validate
|
||||||
|
expect(ident.errors).to be_added(:type, :inclusion)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'accepts valid' do
|
||||||
|
ident.type = 'valid'
|
||||||
|
ident.validate
|
||||||
|
expect(ident.errors).to_not be_added(:type, :inclusion)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'country code validation' do
|
||||||
|
it 'rejects absent' do
|
||||||
|
ident.country_code = nil
|
||||||
|
ident.validate
|
||||||
|
expect(ident.errors).to be_added(:country_code, :blank)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'mismatch validation' do
|
||||||
|
let(:ident) { described_class.new(type: 'test', country_code: 'DE') }
|
||||||
|
|
||||||
|
before do
|
||||||
|
mismatches = [Contact::Ident::MismatchValidator::Mismatch.new('test', Country.new('DE'))]
|
||||||
|
allow(Contact::Ident::MismatchValidator).to receive(:mismatches).and_return(mismatches)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'rejects mismatched' do
|
||||||
|
ident.validate
|
||||||
|
expect(ident.errors).to be_added(:base, :mismatch, type: 'test', country: 'Germany')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'accepts matched' do
|
||||||
|
ident.validate
|
||||||
|
expect(ident.errors).to_not be_added(:base, :mismatch, type: 'another-test', country: 'Germany')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'translates :mismatch error message' do
|
||||||
|
expect(ident.errors.generate_message(:base, :mismatch, type: 'test', country: 'Germany'))
|
||||||
|
.to eq('Ident type "test" is invalid for Germany')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '::types' do
|
||||||
|
it 'returns types' do
|
||||||
|
types = %w[
|
||||||
|
org
|
||||||
|
priv
|
||||||
|
birthday
|
||||||
|
]
|
||||||
|
|
||||||
|
expect(described_class.types).to eq(types)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#birthday?' do
|
||||||
|
context 'when type is birthday' do
|
||||||
|
subject(:ident) { described_class.new(type: 'birthday') }
|
||||||
|
it { is_expected.to be_birthday }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when type is not birthday' do
|
||||||
|
subject(:ident) { described_class.new(type: 'priv') }
|
||||||
|
it { is_expected.to_not be_birthday }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#national_id?' do
|
||||||
|
context 'when type is priv' do
|
||||||
|
subject(:ident) { described_class.new(type: 'priv') }
|
||||||
|
it { is_expected.to be_national_id }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when type is not' do
|
||||||
|
subject(:ident) { described_class.new(type: 'org') }
|
||||||
|
it { is_expected.to_not be_national_id }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#reg_no?' do
|
||||||
|
context 'when type is birthday' do
|
||||||
|
subject(:ident) { described_class.new(type: 'org') }
|
||||||
|
it { is_expected.to be_reg_no }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when type is not birthday' do
|
||||||
|
subject(:ident) { described_class.new(type: 'priv') }
|
||||||
|
it { is_expected.to_not be_reg_no }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#country' do
|
||||||
|
let(:ident) { described_class.new(country_code: 'US') }
|
||||||
|
|
||||||
|
it 'returns country' do
|
||||||
|
expect(ident.country).to eq(Country.new('US'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#==' do
|
||||||
|
let(:ident) { described_class.new(code: 'test', type: 'test', country_code: 'US') }
|
||||||
|
|
||||||
|
context 'when code, type and country code are the same' do
|
||||||
|
let(:another_ident) { described_class.new(code: 'test', type: 'test', country_code: 'US') }
|
||||||
|
|
||||||
|
it 'returns true' do
|
||||||
|
expect(ident).to eq(another_ident)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when code, type and country code are not the same' do
|
||||||
|
let(:another_ident) { described_class.new(code: 'another-test', type: 'test', country_code: 'US') }
|
||||||
|
|
||||||
|
it 'returns false' do
|
||||||
|
expect(ident).to_not eq(another_ident)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -28,45 +28,6 @@ RSpec.describe Contact do
|
||||||
@contact.updator.should == nil
|
@contact.updator.should == nil
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should require country code when org' do
|
|
||||||
@contact.ident_type = 'org'
|
|
||||||
@contact.valid?
|
|
||||||
@contact.errors[:ident_country_code].should == ['is missing']
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should require country code when priv' do
|
|
||||||
@contact.ident_type = 'priv'
|
|
||||||
@contact.valid?
|
|
||||||
@contact.errors[:ident_country_code].should == ['is missing']
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should validate correct country code' do
|
|
||||||
@contact.ident = 1
|
|
||||||
@contact.ident_type = 'org'
|
|
||||||
@contact.ident_country_code = 'EE'
|
|
||||||
@contact.valid?
|
|
||||||
|
|
||||||
@contact.errors[:ident_country_code].should == []
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should require valid country code' do
|
|
||||||
@contact.ident = '123'
|
|
||||||
@contact.ident_type = 'org'
|
|
||||||
@contact.ident_country_code = 'INVALID'
|
|
||||||
@contact.valid?
|
|
||||||
|
|
||||||
expect(@contact.errors).to have_key(:ident)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should convert to alpha2 country code' do
|
|
||||||
@contact.ident = 1
|
|
||||||
@contact.ident_type = 'org'
|
|
||||||
@contact.ident_country_code = 'ee'
|
|
||||||
@contact.validate
|
|
||||||
|
|
||||||
@contact.ident_country_code.should == 'EE'
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should not have any versions' do
|
it 'should not have any versions' do
|
||||||
@contact.versions.should == []
|
@contact.versions.should == []
|
||||||
end
|
end
|
||||||
|
@ -119,14 +80,6 @@ RSpec.describe Contact do
|
||||||
@contact.domains_present?.should == false
|
@contact.domains_present?.should == false
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'org should be valid' do
|
|
||||||
contact = Fabricate.build(:contact, ident_type: 'org', ident: '1' * 8)
|
|
||||||
|
|
||||||
contact.validate
|
|
||||||
|
|
||||||
contact.errors.full_messages.should match_array([])
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should not overwrite code' do
|
it 'should not overwrite code' do
|
||||||
old_code = @contact.code
|
old_code = @contact.code
|
||||||
@contact.code = 'CID:REG1:should-not-overwrite-old-code-12345'
|
@contact.code = 'CID:REG1:should-not-overwrite-old-code-12345'
|
||||||
|
@ -217,31 +170,6 @@ RSpec.describe Contact do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'as birthday' do
|
|
||||||
before :example do
|
|
||||||
@contact.ident_type = 'birthday'
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'birthday should be valid' do
|
|
||||||
valid = ['2012-12-11', '1990-02-16']
|
|
||||||
valid.each do |date|
|
|
||||||
@contact.ident = date
|
|
||||||
@contact.valid?
|
|
||||||
@contact.errors.full_messages.should match_array([])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'birthday should be invalid' do
|
|
||||||
invalid = ['123' '12/12/2012', 'aaaa', '12/12/12', '02-11-1999']
|
|
||||||
invalid.each do |date|
|
|
||||||
@contact.ident = date
|
|
||||||
@contact.valid?
|
|
||||||
@contact.errors.full_messages.should ==
|
|
||||||
["Ident Ident not in valid birthady format, should be YYYY-MM-DD"]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with callbacks' do
|
context 'with callbacks' do
|
||||||
before :example do
|
before :example do
|
||||||
# Ensure callbacks are not taken out from other specs
|
# Ensure callbacks are not taken out from other specs
|
||||||
|
@ -445,7 +373,7 @@ RSpec.describe Contact do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'country code validation' do
|
describe 'country code validation', db: false do
|
||||||
let(:contact) { described_class.new(country_code: 'test') }
|
let(:contact) { described_class.new(country_code: 'test') }
|
||||||
|
|
||||||
it 'rejects invalid' do
|
it 'rejects invalid' do
|
||||||
|
@ -455,37 +383,25 @@ RSpec.describe Contact do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'phone validation', db: false do
|
describe 'identifier validation', db: false do
|
||||||
let(:contact) { described_class.new }
|
let(:contact) { described_class.new }
|
||||||
|
|
||||||
it 'rejects absent' do
|
it 'rejects invalid' do
|
||||||
contact.phone = nil
|
ident = Contact::Ident.new
|
||||||
|
ident.validate
|
||||||
|
contact.identifier = ident
|
||||||
contact.validate
|
contact.validate
|
||||||
expect(contact.errors).to have_key(:phone)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'rejects invalid format' do
|
expect(contact.errors).to be_added(:identifier, :invalid)
|
||||||
contact.phone = '123'
|
|
||||||
contact.validate
|
|
||||||
expect(contact.errors).to have_key(:phone)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'rejects all zeros in country code' do
|
|
||||||
contact.phone = '+000.1'
|
|
||||||
contact.validate
|
|
||||||
expect(contact.errors).to have_key(:phone)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'rejects all zeros in phone number' do
|
|
||||||
contact.phone = '+123.0'
|
|
||||||
contact.validate
|
|
||||||
expect(contact.errors).to have_key(:phone)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'accepts valid' do
|
it 'accepts valid' do
|
||||||
contact.phone = '+123.4'
|
ident = Contact::Ident.new(code: 'test', type: 'priv', country_code: 'US')
|
||||||
|
ident.validate
|
||||||
|
contact.identifier = ident
|
||||||
contact.validate
|
contact.validate
|
||||||
expect(contact.errors).to_not have_key(:phone)
|
|
||||||
|
expect(contact.errors).to_not be_added(:identifier, :invalid)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -595,4 +511,13 @@ RSpec.describe Contact do
|
||||||
expect(domain_names).to eq({ 'test.com' => %i[admin_domain_contact].to_set })
|
expect(domain_names).to eq({ 'test.com' => %i[admin_domain_contact].to_set })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'normalizes ident country code', db: false do
|
||||||
|
contact = described_class.new
|
||||||
|
|
||||||
|
contact.ident_country_code = 'ee'
|
||||||
|
contact.validate
|
||||||
|
|
||||||
|
expect(contact.ident_country_code).to eq('EE')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
21
spec/models/epp/response/result_spec.rb
Normal file
21
spec/models/epp/response/result_spec.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe EPP::Response::Result, db: false do
|
||||||
|
# https://tools.ietf.org/html/rfc5730#section-3
|
||||||
|
describe '::codes' do
|
||||||
|
it 'returns codes' do
|
||||||
|
codes = {
|
||||||
|
'1000' => :success,
|
||||||
|
'1001' => :success_pending,
|
||||||
|
'1300' => :success_empty_queue,
|
||||||
|
'1301' => :success_dequeue,
|
||||||
|
'2001' => :syntax_error,
|
||||||
|
'2003' => :required_param_missing,
|
||||||
|
'2005' => :param_syntax_error,
|
||||||
|
'2308' => :data_management_policy_violation
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(described_class.codes).to eq(codes)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -35,10 +35,6 @@ describe Registrar do
|
||||||
@registrar.reference_no.should_not be_blank
|
@registrar.reference_no.should_not be_blank
|
||||||
@registrar.reference_no.last(10).to_i.should_not == 0
|
@registrar.reference_no.last(10).to_i.should_not == 0
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should not have priv contacts' do
|
|
||||||
@registrar.priv_contacts.size.should == 0
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with valid attributes' do
|
context 'with valid attributes' do
|
||||||
|
@ -120,9 +116,5 @@ describe Registrar do
|
||||||
registrar.valid?
|
registrar.valid?
|
||||||
registrar.errors.full_messages.should == ['Code is forbidden to use']
|
registrar.errors.full_messages.should == ['Code is forbidden to use']
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should not have priv contacts' do
|
|
||||||
@registrar.priv_contacts.size.should == 0
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,6 +10,7 @@ require 'support/requests/epp_helpers'
|
||||||
require 'support/features/session_helpers'
|
require 'support/features/session_helpers'
|
||||||
require 'support/matchers/alias_attribute'
|
require 'support/matchers/alias_attribute'
|
||||||
require 'support/matchers/epp/code'
|
require 'support/matchers/epp/code'
|
||||||
|
require 'support/matchers/epp/have_result'
|
||||||
|
|
||||||
require 'support/capybara'
|
require 'support/capybara'
|
||||||
require 'support/devise'
|
require 'support/devise'
|
||||||
|
@ -28,7 +29,8 @@ RSpec.configure do |config|
|
||||||
config.include AbstractController::Translation, type: :request
|
config.include AbstractController::Translation, type: :request
|
||||||
config.include AbstractController::Translation, type: :feature
|
config.include AbstractController::Translation, type: :feature
|
||||||
config.include AbstractController::Translation, type: :mailer
|
config.include AbstractController::Translation, type: :mailer
|
||||||
config.include Requests::EPPHelpers, type: :request
|
config.include Requests::EPPHelpers, epp: true
|
||||||
|
config.include Matchers::EPP, epp: true
|
||||||
|
|
||||||
config.define_derived_metadata(file_path: %r[/spec/features/]) do |metadata|
|
config.define_derived_metadata(file_path: %r[/spec/features/]) do |metadata|
|
||||||
metadata[:db] = true if metadata[:db].nil?
|
metadata[:db] = true if metadata[:db].nil?
|
||||||
|
|
289
spec/requests/epp/contact/create/ident_spec.rb
Normal file
289
spec/requests/epp/contact/create/ident_spec.rb
Normal file
|
@ -0,0 +1,289 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe 'EPP contact:create' do
|
||||||
|
let(:request) { post '/epp/command/create', frame: request_xml }
|
||||||
|
|
||||||
|
before do
|
||||||
|
Setting.address_processing = false
|
||||||
|
sign_in_to_epp_area
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when all ident params are valid' do
|
||||||
|
let(:ident) { Contact.first.identifier }
|
||||||
|
let(: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>
|
||||||
|
<contact:create xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||||
|
<contact:postalInfo>
|
||||||
|
<contact:name>test</contact:name>
|
||||||
|
</contact:postalInfo>
|
||||||
|
<contact:voice>+1.2</contact:voice>
|
||||||
|
<contact:email>test@test.com</contact:email>
|
||||||
|
</contact:create>
|
||||||
|
</create>
|
||||||
|
<extension>
|
||||||
|
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
|
||||||
|
<eis:ident type="priv" cc="US">test</eis:ident>
|
||||||
|
</eis:extdata>
|
||||||
|
</extension>
|
||||||
|
</command>
|
||||||
|
</epp>
|
||||||
|
XML
|
||||||
|
}
|
||||||
|
|
||||||
|
it 'creates a contact' do
|
||||||
|
expect { request }.to change { Contact.count }.from(0).to(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'saves ident type' do
|
||||||
|
request
|
||||||
|
expect(ident.type).to eq('priv')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'saves ident country code' do
|
||||||
|
request
|
||||||
|
expect(ident.country_code).to eq('US')
|
||||||
|
end
|
||||||
|
|
||||||
|
specify do
|
||||||
|
request
|
||||||
|
expect(epp_response).to have_result(:success)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when code is blank' do
|
||||||
|
let(: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>
|
||||||
|
<contact:create xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||||
|
<contact:postalInfo>
|
||||||
|
<contact:name>test</contact:name>
|
||||||
|
</contact:postalInfo>
|
||||||
|
<contact:voice>+1.2</contact:voice>
|
||||||
|
<contact:email>test@test.com</contact:email>
|
||||||
|
</contact:create>
|
||||||
|
</create>
|
||||||
|
<extension>
|
||||||
|
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
|
||||||
|
<eis:ident type="priv" cc="US"></eis:ident>
|
||||||
|
</eis:extdata>
|
||||||
|
</extension>
|
||||||
|
</command>
|
||||||
|
</epp>
|
||||||
|
XML
|
||||||
|
}
|
||||||
|
|
||||||
|
it 'does not create a contact' do
|
||||||
|
expect { request }.to_not change { Contact.count }
|
||||||
|
end
|
||||||
|
|
||||||
|
specify do
|
||||||
|
request
|
||||||
|
expect(epp_response).to have_result(:required_param_missing,
|
||||||
|
'Required parameter missing: extension > extdata > ident [ident]')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when code is not valid national id' do
|
||||||
|
let(: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>
|
||||||
|
<contact:create xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||||
|
<contact:postalInfo>
|
||||||
|
<contact:name>test</contact:name>
|
||||||
|
</contact:postalInfo>
|
||||||
|
<contact:voice>+1.2</contact:voice>
|
||||||
|
<contact:email>test@test.com</contact:email>
|
||||||
|
</contact:create>
|
||||||
|
</create>
|
||||||
|
<extension>
|
||||||
|
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
|
||||||
|
<eis:ident type="priv" cc="DE">invalid</eis:ident>
|
||||||
|
</eis:extdata>
|
||||||
|
</extension>
|
||||||
|
</command>
|
||||||
|
</epp>
|
||||||
|
XML
|
||||||
|
}
|
||||||
|
|
||||||
|
before do
|
||||||
|
country_specific_validations = {
|
||||||
|
Country.new('DE') => proc { false },
|
||||||
|
}
|
||||||
|
|
||||||
|
allow(Contact::Ident::NationalIdValidator).to receive(:country_specific_validations)
|
||||||
|
.and_return(country_specific_validations)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not create a contact' do
|
||||||
|
expect { request }.to_not change { Contact.count }
|
||||||
|
end
|
||||||
|
|
||||||
|
specify do
|
||||||
|
request
|
||||||
|
|
||||||
|
message = 'Ident code does not conform to national identification number format of Germany'
|
||||||
|
expect(epp_response).to have_result(:param_syntax_error, message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when code is not valid registration number' do
|
||||||
|
let(: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>
|
||||||
|
<contact:create xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||||
|
<contact:postalInfo>
|
||||||
|
<contact:name>test</contact:name>
|
||||||
|
</contact:postalInfo>
|
||||||
|
<contact:voice>+1.2</contact:voice>
|
||||||
|
<contact:email>test@test.com</contact:email>
|
||||||
|
</contact:create>
|
||||||
|
</create>
|
||||||
|
<extension>
|
||||||
|
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
|
||||||
|
<eis:ident type="org" cc="DE">invalid</eis:ident>
|
||||||
|
</eis:extdata>
|
||||||
|
</extension>
|
||||||
|
</command>
|
||||||
|
</epp>
|
||||||
|
XML
|
||||||
|
}
|
||||||
|
|
||||||
|
before do
|
||||||
|
country_specific_formats = {
|
||||||
|
Country.new('DE') => /\Avalid\z/,
|
||||||
|
}
|
||||||
|
|
||||||
|
allow(Contact::Ident::RegNoValidator).to receive(:country_specific_formats).and_return(country_specific_formats)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not create a contact' do
|
||||||
|
expect { request }.to_not change { Contact.count }
|
||||||
|
end
|
||||||
|
|
||||||
|
specify do
|
||||||
|
request
|
||||||
|
expect(epp_response).to have_result(:param_syntax_error,
|
||||||
|
'Ident code does not conform to registration number format of Germany')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when country code is absent' do
|
||||||
|
let(: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>
|
||||||
|
<contact:create xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||||
|
<contact:postalInfo>
|
||||||
|
<contact:name>test</contact:name>
|
||||||
|
</contact:postalInfo>
|
||||||
|
<contact:voice>+1.2</contact:voice>
|
||||||
|
<contact:email>test@test.com</contact:email>
|
||||||
|
</contact:create>
|
||||||
|
</create>
|
||||||
|
<extension>
|
||||||
|
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
|
||||||
|
<eis:ident type="priv">test</eis:ident>
|
||||||
|
</eis:extdata>
|
||||||
|
</extension>
|
||||||
|
</command>
|
||||||
|
</epp>
|
||||||
|
XML
|
||||||
|
}
|
||||||
|
|
||||||
|
it 'does not create a contact' do
|
||||||
|
expect { request }.to_not change { Contact.count }
|
||||||
|
end
|
||||||
|
|
||||||
|
specify do
|
||||||
|
request
|
||||||
|
expect(epp_response).to have_result(:required_param_missing,
|
||||||
|
'Required ident attribute missing: cc')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when country code is blank' do
|
||||||
|
let(: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>
|
||||||
|
<contact:create xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||||
|
<contact:postalInfo>
|
||||||
|
<contact:name>test</contact:name>
|
||||||
|
</contact:postalInfo>
|
||||||
|
<contact:voice>+1.2</contact:voice>
|
||||||
|
<contact:email>test@test.com</contact:email>
|
||||||
|
</contact:create>
|
||||||
|
</create>
|
||||||
|
<extension>
|
||||||
|
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
|
||||||
|
<eis:ident type="priv" cc="">test</eis:ident>
|
||||||
|
</eis:extdata>
|
||||||
|
</extension>
|
||||||
|
</command>
|
||||||
|
</epp>
|
||||||
|
XML
|
||||||
|
}
|
||||||
|
|
||||||
|
it 'does not create a contact' do
|
||||||
|
expect { request }.to_not change { Contact.count }
|
||||||
|
end
|
||||||
|
|
||||||
|
specify do
|
||||||
|
request
|
||||||
|
expect(epp_response).to have_result(:syntax_error)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when mismatches' do
|
||||||
|
let(: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>
|
||||||
|
<contact:create xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||||
|
<contact:postalInfo>
|
||||||
|
<contact:name>test</contact:name>
|
||||||
|
</contact:postalInfo>
|
||||||
|
<contact:voice>+1.2</contact:voice>
|
||||||
|
<contact:email>test@test.com</contact:email>
|
||||||
|
</contact:create>
|
||||||
|
</create>
|
||||||
|
<extension>
|
||||||
|
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
|
||||||
|
<eis:ident type="priv" cc="DE">test</eis:ident>
|
||||||
|
</eis:extdata>
|
||||||
|
</extension>
|
||||||
|
</command>
|
||||||
|
</epp>
|
||||||
|
XML
|
||||||
|
}
|
||||||
|
|
||||||
|
before do
|
||||||
|
mismatches = [
|
||||||
|
Contact::Ident::MismatchValidator::Mismatch.new('priv', Country.new('DE'))
|
||||||
|
]
|
||||||
|
allow(Contact::Ident::MismatchValidator).to receive(:mismatches).and_return(mismatches)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not create a contact' do
|
||||||
|
expect { request }.to_not change { Contact.count }
|
||||||
|
end
|
||||||
|
|
||||||
|
specify do
|
||||||
|
request
|
||||||
|
expect(epp_response).to have_result(:param_syntax_error,
|
||||||
|
'Ident type "priv" is invalid for Germany')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
196
spec/requests/epp/contact/update/ident_spec.rb
Normal file
196
spec/requests/epp/contact/update/ident_spec.rb
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
# https://github.com/internetee/registry/issues/576
|
||||||
|
|
||||||
|
RSpec.describe 'EPP contact:update' do
|
||||||
|
let(:ident) { contact.identifier }
|
||||||
|
let(:request) { post '/epp/command/update', frame: request_xml }
|
||||||
|
let(: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>
|
||||||
|
<update>
|
||||||
|
<contact:update xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||||
|
<contact:id>TEST</contact:id>
|
||||||
|
<contact:chg>
|
||||||
|
<contact:postalInfo>
|
||||||
|
<contact:name>test</contact:name>
|
||||||
|
</contact:postalInfo>
|
||||||
|
</contact:chg>
|
||||||
|
</contact:update>
|
||||||
|
</update>
|
||||||
|
<extension>
|
||||||
|
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
|
||||||
|
<eis:ident cc="US" type="priv">test</eis:ident>
|
||||||
|
</eis:extdata>
|
||||||
|
</extension>
|
||||||
|
</command>
|
||||||
|
</epp>
|
||||||
|
XML
|
||||||
|
}
|
||||||
|
|
||||||
|
before do
|
||||||
|
sign_in_to_epp_area
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when contact ident is valid' do
|
||||||
|
context 'when submitted ident matches current one' do
|
||||||
|
let!(:contact) { create(:contact, code: 'TEST',
|
||||||
|
ident: 'test',
|
||||||
|
ident_type: 'priv',
|
||||||
|
ident_country_code: 'US') }
|
||||||
|
|
||||||
|
specify do
|
||||||
|
request
|
||||||
|
expect(epp_response).to have_result(:success)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when submitted ident does not match current one' do
|
||||||
|
let!(:contact) { create(:contact, code: 'TEST',
|
||||||
|
ident: 'another-test',
|
||||||
|
ident_type: 'priv',
|
||||||
|
ident_country_code: 'US') }
|
||||||
|
|
||||||
|
it 'does not update code' do
|
||||||
|
expect do
|
||||||
|
request
|
||||||
|
contact.reload
|
||||||
|
end.to_not change { ident.code }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not update type' do
|
||||||
|
expect do
|
||||||
|
request
|
||||||
|
contact.reload
|
||||||
|
end.to_not change { ident.type }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not update country code' do
|
||||||
|
expect do
|
||||||
|
request
|
||||||
|
contact.reload
|
||||||
|
end.to_not change { ident.country_code }
|
||||||
|
end
|
||||||
|
|
||||||
|
specify do
|
||||||
|
request
|
||||||
|
|
||||||
|
expect(epp_response).to have_result(:data_management_policy_violation,
|
||||||
|
t('epp.contacts.errors.valid_ident'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when contact ident is invalid' do
|
||||||
|
let(:contact) { build(:contact, code: 'TEST', ident: 'test', ident_type: nil, ident_country_code: nil) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
contact.save(validate: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when submitted ident is the same as current one' do
|
||||||
|
let(: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>
|
||||||
|
<update>
|
||||||
|
<contact:update xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||||
|
<contact:id>TEST</contact:id>
|
||||||
|
<contact:chg>
|
||||||
|
<contact:postalInfo>
|
||||||
|
<contact:name>test</contact:name>
|
||||||
|
</contact:postalInfo>
|
||||||
|
</contact:chg>
|
||||||
|
</contact:update>
|
||||||
|
</update>
|
||||||
|
<extension>
|
||||||
|
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
|
||||||
|
<eis:ident cc="US" type="priv">test</eis:ident>
|
||||||
|
</eis:extdata>
|
||||||
|
</extension>
|
||||||
|
</command>
|
||||||
|
</epp>
|
||||||
|
XML
|
||||||
|
}
|
||||||
|
|
||||||
|
it 'does not update code' do
|
||||||
|
expect do
|
||||||
|
request
|
||||||
|
contact.reload
|
||||||
|
end.to_not change { ident.code }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates type' do
|
||||||
|
request
|
||||||
|
contact.reload
|
||||||
|
expect(ident.type).to eq('priv')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates country code' do
|
||||||
|
request
|
||||||
|
contact.reload
|
||||||
|
expect(ident.country_code).to eq('US')
|
||||||
|
end
|
||||||
|
|
||||||
|
specify do
|
||||||
|
request
|
||||||
|
expect(epp_response).to have_result(:success)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when submitted ident is different from current one' do
|
||||||
|
let(: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>
|
||||||
|
<update>
|
||||||
|
<contact:update xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
|
||||||
|
<contact:id>TEST</contact:id>
|
||||||
|
<contact:chg>
|
||||||
|
<contact:postalInfo>
|
||||||
|
<contact:name>test</contact:name>
|
||||||
|
</contact:postalInfo>
|
||||||
|
</contact:chg>
|
||||||
|
</contact:update>
|
||||||
|
</update>
|
||||||
|
<extension>
|
||||||
|
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
|
||||||
|
<eis:ident cc="US" type="priv">another-test</eis:ident>
|
||||||
|
</eis:extdata>
|
||||||
|
</extension>
|
||||||
|
</command>
|
||||||
|
</epp>
|
||||||
|
XML
|
||||||
|
}
|
||||||
|
|
||||||
|
it 'does not update code' do
|
||||||
|
expect do
|
||||||
|
request
|
||||||
|
contact.reload
|
||||||
|
end.to_not change { ident.code }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not update type' do
|
||||||
|
expect do
|
||||||
|
request
|
||||||
|
contact.reload
|
||||||
|
end.to_not change { ident.type }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not update country code' do
|
||||||
|
expect do
|
||||||
|
request
|
||||||
|
contact.reload
|
||||||
|
end.to_not change { ident.country_code }
|
||||||
|
end
|
||||||
|
|
||||||
|
specify do
|
||||||
|
request
|
||||||
|
|
||||||
|
expect(epp_response).to have_result(:data_management_policy_violation,
|
||||||
|
t('epp.contacts.errors.ident_update'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
37
spec/support/matchers/epp/have_result.rb
Normal file
37
spec/support/matchers/epp/have_result.rb
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
module Matchers
|
||||||
|
module EPP
|
||||||
|
class HaveResultMatcher
|
||||||
|
def initialize(expected)
|
||||||
|
@expected = expected
|
||||||
|
end
|
||||||
|
|
||||||
|
def matches?(target)
|
||||||
|
@target = target
|
||||||
|
|
||||||
|
if @expected.message.present?
|
||||||
|
@target.results.any? { |result| result.code == @expected.code && result.message == @expected.message }
|
||||||
|
else
|
||||||
|
@target.results.any? { |result| result.code == @expected.code }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def failure_message
|
||||||
|
"expected #{@target.results} to have result #{@expected.inspect}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def failure_message_when_negated
|
||||||
|
"expected #{@target.results} not to have result #{@expected.inspect}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def description
|
||||||
|
"should have EPP code of #{@expected}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def have_result(type, message = nil)
|
||||||
|
code = ::EPP::Response::Result.codes.key(type)
|
||||||
|
result = ::EPP::Response::Result.new(code, message)
|
||||||
|
HaveResultMatcher.new(result)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,5 +7,9 @@ module Requests
|
||||||
def valid_legal_document
|
def valid_legal_document
|
||||||
Base64.encode64('a' * 5000)
|
Base64.encode64('a' * 5000)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def epp_response
|
||||||
|
EPP::Response.from_xml(response.body)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
13
spec/validators/contact/ident/mismatch_validator_spec.rb
Normal file
13
spec/validators/contact/ident/mismatch_validator_spec.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Contact::Ident::MismatchValidator do
|
||||||
|
describe '::mismatches' do
|
||||||
|
it 'returns mismatches' do
|
||||||
|
mismatches = [
|
||||||
|
Contact::Ident::MismatchValidator::Mismatch.new('birthday', Country.new('EE'))
|
||||||
|
]
|
||||||
|
|
||||||
|
expect(described_class.mismatches).to eq(mismatches)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Add table
Add a link
Reference in a new issue