diff --git a/Guardfile b/Guardfile index eab74ee21..955ca3b4e 100644 --- a/Guardfile +++ b/Guardfile @@ -3,11 +3,11 @@ group :red_green_refactor, halt_on_fail: true do # be sure you have apache2 configured to # accept EPP request on port 701, what proxy to 8989. # port and environment is just for correct notification, all is overwritten by CLI - guard :rails, port: 8989, environment: 'test' do - # guard :rails, port: 8989, environment: 'test', CLI: 'RAILS_ENV=test unicorn -p 8989' do - watch('Gemfile.lock') - watch(%r{^(config|lib)/.*}) - end + # guard :rails, port: 8989, environment: 'test' do + # # guard :rails, port: 8989, environment: 'test', CLI: 'RAILS_ENV=test unicorn -p 8989' do + # watch('Gemfile.lock') + # watch(%r{^(config|lib)/.*}) + # end guard :rspec, cmd: 'spring rspec', notification: false do watch(%r{^spec/.+_spec\.rb$}) diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index 9810f7bdf..8bea17fdf 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -1,4 +1,3 @@ class AdminController < ApplicationController before_action :authenticate_user! - check_authorization end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 81acf1313..698cbfa88 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,4 +1,6 @@ class ApplicationController < ActionController::Base + check_authorization + # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception @@ -9,8 +11,22 @@ class ApplicationController < ActionController::Base params[resource] &&= send(method) if respond_to?(method, true) end + rescue_from CanCan::AccessDenied do |exception| + redirect_to admin_dashboard_path, alert: exception.message + end + + def current_ability + if defined?(current_api_user) && current_api_user.present? + current_api_user.ability + else + current_user.ability + end + end + def after_sign_in_path_for(_resource) - return session[:user_return_to].to_s if session[:user_return_to] && session[:user_return_to] != login_path + if session[:user_return_to] && session[:user_return_to] != login_path + return session[:user_return_to].to_s + end admin_dashboard_path end @@ -34,9 +50,3 @@ class ApplicationController < ActionController::Base end end end - -class ApplicationController < ActionController::Base - rescue_from CanCan::AccessDenied do |exception| - redirect_to admin_dashboard_path, alert: exception.message - end -end diff --git a/app/controllers/epp/contacts_controller.rb b/app/controllers/epp/contacts_controller.rb index fefdce438..c25050aad 100644 --- a/app/controllers/epp/contacts_controller.rb +++ b/app/controllers/epp/contacts_controller.rb @@ -1,183 +1,114 @@ class Epp::ContactsController < EppController + before_action :find_contact, only: [:info, :update, :delete] + before_action :find_password, only: [:info, :update, :delete] + def info - handle_errors(@contact) and return unless @contact && rights? - # handle_errors(@contact) and return unless rights? - @disclosure = ContactDisclosure.default_values.merge(@contact.disclosure.try(:as_hash) || {}) - @disclosure_policy = @contact.disclosure.try(:attributes_with_flag) - @owner = owner?(false) - # need to reload contact eagerly - @contact = find_contact if @owner # for clarity, could just be true + authorize! :info, @contact, @password render_epp_response 'epp/contacts/info' end - def create - @contact = Contact.new(contact_and_address_attributes) - @contact.registrar = current_user.registrar - render_epp_response '/epp/contacts/create' and return if @contact.save - handle_errors(@contact) - end - - def update - # FIXME: Update returns 2303 update multiple times - code = params_hash['epp']['command']['update']['update'][:id] - - @contact = Contact.where(code: code).first - # if update_rights? && @contact.update_attributes(contact_and_address_attributes(:update)) - if owner? && @contact.update_attributes(contact_and_address_attributes(:update)) - render_epp_response 'epp/contacts/update' - else - contact_exists?(code) - handle_errors(@contact) and return - end - end - - # rubocop:disable Metrics/CyclomaticComplexity - def delete - @contact = find_contact - handle_errors(@contact) and return unless rights? # owner? - handle_errors(@contact) and return unless @contact - handle_errors(@contact) and return unless @contact.destroy_and_clean - - render_epp_response '/epp/contacts/delete' - end - # rubocop:enable Metrics/CyclomaticComplexity - def check - ph = params_hash['epp']['command']['check']['check'] - @contacts = Contact.check_availability(ph[:id]) + authorize! :check, Epp::Contact + + ids = params[:parsed_frame].css('id').map(&:text) + @results = Contact.check_availability(ids) render_epp_response '/epp/contacts/check' end + def create + authorize! :create, Epp::Contact + + @contact = Epp::Contact.new(params[:parsed_frame]) + @contact.registrar = current_user.registrar + + if @contact.save + render_epp_response '/epp/contacts/create' + else + handle_errors(@contact) + end + end + + def update + authorize! :update, @contact, @password + + if @contact.update_attributes(params[:parsed_frame]) + render_epp_response 'epp/contacts/update' + else + handle_errors(@contact) + end + end + + def delete + authorize! :delete, @contact, @password + + if @contact.destroy_and_clean + render_epp_response '/epp/contacts/delete' + else + handle_errors(@contact) + end + end + def renew + authorize! :renew, Epp::Contact epp_errors << { code: '2101', msg: t(:'errors.messages.unimplemented_command') } handle_errors end - ## HELPER METHODS - private - ## CREATE - def validate_create - @prefix = 'create > create >' - requires 'postalInfo > name', 'postalInfo > addr > city', - 'postalInfo > addr > cc', 'ident', 'voice', 'email' + def find_password + @password = params[:parsed_frame].css('authInfo pw').text + end + + def find_contact + code = params[:parsed_frame].css('id').text.strip.downcase + @contact = Epp::Contact.find_by(code: code) + + if @contact.blank? + epp_errors << { + code: '2303', + msg: t('errors.messages.epp_obj_does_not_exist'), + value: { obj: 'id', val: code } + } + fail CanCan::AccessDenied + end + @contact + end + + # + # Validations + # + def validate_info + @prefix = 'info > info >' + requires 'id' + end + + def validate_check + @prefix = 'check > check >' + requires 'id' + end + + def validate_create + @prefix = 'create > create >' + requires( + 'postalInfo > name', 'postalInfo > addr > city', + 'postalInfo > addr > cc', 'ident', 'voice', 'email' + ) end - ## UPDATE def validate_update @prefix = 'update > update >' - requires 'id' - if element_count('chg') == 0 && element_count('rem') == 0 && element_count('add') == 0 epp_errors << { code: '2003', msg: I18n.t('errors.messages.required_parameter_missing', key: 'add, rem or chg') } end + requires 'id', 'authInfo > pw' end - def contact_exists?(code) - return true if @contact.is_a?(Contact) - epp_errors << { code: '2303', msg: t('errors.messages.epp_obj_does_not_exist'), - value: { obj: 'id', val: code } } - end - - ## DELETE def validate_delete - @ph = params_hash['epp']['command']['delete']['delete'] - xml_attrs_present?(@ph, [['id']]) - end - - ## check - def validate_check - @ph = params_hash['epp']['command']['check']['check'] - xml_attrs_present?(@ph, [['id']]) - end - - ## info - def validate_info # and process - @ph = params_hash['epp']['command']['info']['info'] - return false unless xml_attrs_present?(@ph, [['id']]) - @contact = find_contact - return false unless @contact - return true if current_user.registrar == @contact.registrar || xml_attrs_present?(@ph, [%w(authInfo pw)]) - false - end - - ## SHARED - - def find_contact - contact_code = params[:parsed_frame].css('id').text.strip.downcase - contact = Contact.find_by(code: contact_code) - - if contact.blank? - epp_errors << { code: '2303', - msg: t('errors.messages.epp_obj_does_not_exist'), - value: { obj: 'id', val: contact_code } } - end - contact - end - - def owner?(with_errors = true) - return false unless find_contact - return true if @contact.registrar == current_user.registrar - return false unless with_errors - epp_errors << { code: '2201', msg: t('errors.messages.epp_authorization_error') } - false - end - - def rights? - pw = @ph.try(:[], :authInfo).try(:[], :pw) - - return true if current_user.try(:registrar) == @contact.try(:registrar) - return true if pw && @contact.auth_info_matches(pw) # @contact.try(:auth_info_matches, pw) - - epp_errors << { code: '2200', msg: t('errors.messages.epp_authentication_error') } - false - end - - def update_rights? - pw = @ph.try(:[], :authInfo).try(:[], :pw) - return true if pw && @contact.auth_info_matches(pw) - epp_errors << { code: '2200', msg: t('errors.messages.epp_authentication_error') } - false - end - - def contact_and_address_attributes(type = :create) - case type - when :update - # TODO: support for rem/add - contact_hash = merge_attribute_hash(@ph[:chg], type).delete_if { |_k, v| v.empty? } - else - contact_hash = merge_attribute_hash(@ph, type) - end - contact_hash[:ident_type] = ident_type unless ident_type.nil? - contact_hash - end - - def merge_attribute_hash(prms, type) - contact_hash = Contact.extract_attributes(prms, type) - contact_hash = contact_hash.merge( - Address.extract_attributes((prms.try(:[], :postalInfo) || [])) - ) - contact_hash[:disclosure_attributes] = - ContactDisclosure.extract_attributes(params[:parsed_frame]) - - contact_hash - end - - def ident_type - result = params[:parsed_frame].css('ident').first.try(:attributes).try(:[], 'type').try(:value) - return nil unless result - - Contact::IDENT_TYPES.any? { |type| return type if result.include?(type) } - nil - end - - def validate_params - return true if @ph - epp_errors << { code: '2001', msg: t(:'errors.messages.epp_command_syntax_error') } - false + @prefix = 'delete > delete >' + requires 'id', 'authInfo > pw' end end diff --git a/app/controllers/epp/domains_controller.rb b/app/controllers/epp/domains_controller.rb index 319c1c041..eac99120e 100644 --- a/app/controllers/epp/domains_controller.rb +++ b/app/controllers/epp/domains_controller.rb @@ -1,4 +1,6 @@ class Epp::DomainsController < EppController + skip_authorization_check # TODO: remove it + def create @domain = Epp::EppDomain.new(domain_create_params) diff --git a/app/controllers/epp/errors_controller.rb b/app/controllers/epp/errors_controller.rb index 43b8ee6b1..cefa026a0 100644 --- a/app/controllers/epp/errors_controller.rb +++ b/app/controllers/epp/errors_controller.rb @@ -1,4 +1,6 @@ class Epp::ErrorsController < EppController + skip_authorization_check # TODO: remove it + def error epp_errors << { code: params[:code], msg: params[:msg] } render_epp_response '/epp/error' diff --git a/app/controllers/epp/keyrelays_controller.rb b/app/controllers/epp/keyrelays_controller.rb index f84694e5b..8a9b863d4 100644 --- a/app/controllers/epp/keyrelays_controller.rb +++ b/app/controllers/epp/keyrelays_controller.rb @@ -1,4 +1,6 @@ class Epp::KeyrelaysController < EppController + skip_authorization_check # TODO: remove it + # rubocop: disable Metrics/PerceivedComplexity # rubocop: disable Metrics/CyclomaticComplexity def keyrelay diff --git a/app/controllers/epp/polls_controller.rb b/app/controllers/epp/polls_controller.rb index 3376956e2..2f445abc6 100644 --- a/app/controllers/epp/polls_controller.rb +++ b/app/controllers/epp/polls_controller.rb @@ -1,4 +1,6 @@ class Epp::PollsController < EppController + skip_authorization_check # TODO: remove it + def poll req_poll if params[:parsed_frame].css('poll').first['op'] == 'req' ack_poll if params[:parsed_frame].css('poll').first['op'] == 'ack' @@ -38,6 +40,6 @@ class Epp::PollsController < EppController private def validate_poll - requires_attribute 'poll', 'op', values: %(ack req) + requires_attribute 'poll', 'op', values: %(ack req), allow_blank: true end end diff --git a/app/controllers/epp/sessions_controller.rb b/app/controllers/epp/sessions_controller.rb index 1485001a8..21161c7a0 100644 --- a/app/controllers/epp/sessions_controller.rb +++ b/app/controllers/epp/sessions_controller.rb @@ -1,4 +1,6 @@ class Epp::SessionsController < EppController + skip_authorization_check only: [:hello, :login, :logout] + def hello render_epp_response('greeting') end diff --git a/app/controllers/epp_controller.rb b/app/controllers/epp_controller.rb index 4749c1ff0..89623117c 100644 --- a/app/controllers/epp_controller.rb +++ b/app/controllers/epp_controller.rb @@ -1,10 +1,23 @@ class EppController < ApplicationController + layout false protect_from_forgery with: :null_session + skip_before_action :verify_authenticity_token + before_action :generate_svtrid before_action :validate_request - layout false helper_method :current_user + rescue_from CanCan::AccessDenied do |_exception| + @errors ||= [] + if @errors.blank? + @errors = [{ + msg: t('errors.messages.epp_authorization_error'), + code: '2201' + }] + end + render_epp_response '/epp/error' + end + def generate_svtrid # rubocop: disable Style/VariableName @svTRID = "ccReg-#{format('%010d', rand(10**10))}" @@ -112,7 +125,7 @@ class EppController < ApplicationController # requires_attribute 'transfer', 'op', values: %(approve, query, reject) def requires_attribute(element_selector, attribute_selector, options) - element = requires(element_selector) + element = requires(element_selector, allow_blank: options[:allow_blank]) return unless element attribute = element[attribute_selector] diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index a6c1a9ff6..7e1247c1a 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,4 +1,6 @@ class SessionsController < Devise::SessionsController + skip_authorization_check only: [:login, :create] + def create # TODO: Create ID Card login here: # this is just testing config diff --git a/app/models/ability.rb b/app/models/ability.rb index 47fc6c209..9980e9709 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -2,16 +2,25 @@ class Ability include CanCan::Ability def initialize(user) - alias_action :create, :read, :update, :destroy, to: :crud + alias_action :show, :create, :update, :destroy, to: :crud @user = user || AdminUser.new @user.roles.each { |role| send(role) } if @user.roles - return if @user.roles || @user.roles.any? - can :show, :dashboard end + def epp + # Epp::Contact + can(:info, Epp::Contact) { |c, pw| c.registrar_id == @user.registrar_id || c.auth_info == pw } + can(:check, Epp::Contact) + can(:create, Epp::Contact) + can(:update, Epp::Contact) { |c, pw| c.registrar_id == @user.registrar_id && c.auth_info == pw } + can(:delete, Epp::Contact) { |c, pw| c.registrar_id == @user.registrar_id && c.auth_info == pw } + can(:renew, Epp::Contact) + can(:view_password, Epp::Contact) { |c| c.registrar_id == @user.registrar_id } + end + def user can :show, :dashboard end diff --git a/app/models/api_user.rb b/app/models/api_user.rb index a067d00f1..aee1ff203 100644 --- a/app/models/api_user.rb +++ b/app/models/api_user.rb @@ -13,6 +13,11 @@ class ApiUser < User attr_accessor :registrar_typeahead + def ability + @ability ||= Ability.new(self) + end + delegate :can?, :cannot?, to: :ability + def registrar_typeahead @registrar_typeahead || registrar || nil end diff --git a/app/models/concerns/version_session.rb b/app/models/concerns/version_session.rb index 50095f2c1..4d455d784 100644 --- a/app/models/concerns/version_session.rb +++ b/app/models/concerns/version_session.rb @@ -5,7 +5,7 @@ module VersionSession before_save :add_session def add_session - self.session = PaperSession.session + self.session = ::PaperSession.session true end end diff --git a/app/models/concerns/versions.rb b/app/models/concerns/versions.rb index d14501e74..8918647f1 100644 --- a/app/models/concerns/versions.rb +++ b/app/models/concerns/versions.rb @@ -28,9 +28,9 @@ module Versions return nil if creator_str.blank? if creator_str =~ /^\d-api-/ - ApiUser.find(creator_str) + ApiUser.find_by(id: creator_str) else - AdminUser.find(creator_str) + AdminUser.find_by(id: creator_str) end end @@ -38,9 +38,9 @@ module Versions return nil if updator_str.blank? if updator_str =~ /^\d-api-/ - ApiUser.find(updator_str) + ApiUser.find_by(id: updator_str) else - AdminUser.find(updator_str) + AdminUser.find_by(id: updator_str) end end diff --git a/app/models/contact.rb b/app/models/contact.rb index 4238924b0..539c0d1a2 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -1,6 +1,5 @@ class Contact < ActiveRecord::Base include Versions # version/contact_version.rb - include EppErrors has_one :address, dependent: :destroy has_one :disclosure, class_name: 'ContactDisclosure', dependent: :destroy @@ -19,25 +18,20 @@ class Contact < ActiveRecord::Base validates :phone, format: /\+[0-9]{1,3}\.[0-9]{1,14}?/ validates :email, format: /@/ validates :ident, format: /\d{4}-\d{2}-\d{2}/, if: proc { |c| c.ident_type == 'birthday' } - validate :ident_must_be_valid - validates :code, uniqueness: { message: :epp_id_taken } - delegate :city, to: :address # , prefix: true - delegate :street, to: :address # , prefix: true - delegate :zip, to: :address # , prefix: true + delegate :street, to: :address + delegate :city, to: :address + delegate :zip, to: :address + delegate :state, to: :address + delegate :country_code, to: :address + delegate :country, to: :address - # callbacks - # TODO: remove old - # after_commit :domains_snapshot - # after_update :domains_snapshot - # after_destroy :domains_snapshot before_create :generate_code before_create :generate_auth_info after_create :ensure_disclosure - # scopes scope :current_registrars, ->(id) { where(registrar_id: id) } IDENT_TYPE_ICO = 'ico' @@ -54,6 +48,32 @@ class Contact < ActiveRecord::Base CONTACT_TYPE_ADMIN = 'admin' CONTACT_TYPES = [CONTACT_TYPE_TECH, CONTACT_TYPE_ADMIN] + class << self + def search_by_query(query) + res = search(code_cont: query).result + res.reduce([]) { |o, v| o << { id: v[:id], display_key: "#{v.name} (#{v.code})" } } + end + + def check_availability(codes) + codes = [codes] if codes.is_a?(String) + + res = [] + codes.each do |x| + if Contact.find_by(code: x) + res << { code: x, avail: 0, reason: 'in use' } + else + res << { code: x, avail: 1 } + end + end + + res + end + end + + def to_s + name + end + def ident_must_be_valid # TODO: Ident can also be passport number or company registry code. # so have to make changes to validations (and doc/schema) accordingly @@ -66,15 +86,6 @@ class Contact < ActiveRecord::Base create_disclosure! unless disclosure end - # TODO: remove old - # def domains_snapshot - # (domains + domains_owned).uniq.each do |domain| - # next unless domain.is_a?(Domain) - # # next if domain.versions.last == domain.create_snapshot - # domain.create_version # Method from paper_trail - # end - # end - def juridical? ident_type == IDENT_TYPE_ICO end @@ -83,18 +94,6 @@ class Contact < ActiveRecord::Base ident_type != IDENT_TYPE_ICO end - def cr_id - # created_by ? created_by.username : nil - end - - def up_id - # updated_by ? updated_by.username : nil - end - - def auth_info_matches(pw) - auth_info == pw - end - # generate random id for contact def generate_code self.code = SecureRandom.hex(4) @@ -114,6 +113,8 @@ class Contact < ActiveRecord::Base false end + # TODO: refactor, it should not allow to destroy with normal destroy, + # no need separate method # should use only in transaction def destroy_and_clean if relations_with_domain? @@ -122,76 +123,4 @@ class Contact < ActiveRecord::Base end destroy end - - def epp_code_map # rubocop:disable Metrics/MethodLength - { - '2302' => [ # Object exists - [:code, :epp_id_taken] - ], - '2305' => [ # Association exists - [:domains, :exist] - ], - '2005' => [ # Value syntax error - [:phone, :invalid], - [:email, :invalid], - [:ident, :invalid] - ] - } - end - - def to_s - name - end - - # TODO: remove old - # for archiving - # def snapshot - # { - # name: name, - # phone: phone, - # code: code, - # ident: ident, - # email: email - # } - # end - - class << self - # non-EPP - - # EPP - 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], - ident_type: ph[:ident_type], - 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.delete_if { |_k, v| v.nil? } - end - - def check_availability(codes) - codes = [codes] if codes.is_a?(String) - - res = [] - codes.each do |x| - if Contact.find_by(code: x) - res << { code: x, avail: 0, reason: 'in use' } - else - res << { code: x, avail: 1 } - end - end - - res - end - - def search_by_query(query) - res = search(code_cont: query).result - res.reduce([]) { |o, v| o << { id: v[:id], display_key: "#{v.name} (#{v.code})" } } - end - end end diff --git a/app/models/epp/contact.rb b/app/models/epp/contact.rb new file mode 100644 index 000000000..bb0af23cd --- /dev/null +++ b/app/models/epp/contact.rb @@ -0,0 +1,87 @@ +# rubocop: disable Metrics/ClassLength +class Epp::Contact < Contact + include EppErrors + + # disable STI, there is type column present + self.inheritance_column = :sti_disabled + + class << self + # rubocop: disable Metrics/PerceivedComplexity + # rubocop: disable Metrics/CyclomaticComplexity + def attrs_from(frame) + f = frame + at = {}.with_indifferent_access + at[:name] = f.css('postalInfo name').text if f.css('postalInfo name').present? + at[:org_name] = f.css('postalInfo org').text if f.css('postalInfo org').present? + at[:email] = f.css('email').text if f.css('email').present? + at[:fax] = f.css('fax').text if f.css('fax').present? + at[:phone] = f.css('voice').text if f.css('voice').present? + at[:auth_info] = f.css('authInfo pw').text if f.css('authInfo pw').present? + + if f.css('ident').present? && f.css('ident').attr('type').present? + at[:ident] = f.css('ident').text + at[:ident_type] = f.css('ident').attr('type').text + end + + at[:address_attributes] = {} + sat = at[:address_attributes] + sat[:city] = f.css('postalInfo addr city').text if f.css('postalInfo addr city').present? + sat[:zip] = f.css('postalInfo addr pc').text if f.css('postalInfo addr pc').present? + sat[:street] = f.css('postalInfo addr street').text if f.css('postalInfo addr street').present? + sat[:state] = f.css('postalInfo addr sp').text if f.css('postalInfo addr sp').present? + sat[:country_code] = f.css('postalInfo addr cc').text if f.css('postalInfo addr cc').present? + at.delete(:address_attributes) if at[:address_attributes].blank? + at + end + # rubocop: enable Metrics/PerceivedComplexity + # rubocop: enable Metrics/CyclomaticComplexity + + def new(frame) + return super if frame.blank? + super(attrs_from(frame)) + end + + def parse_legal_document_from_frame(parsed_frame) + ld = parsed_frame.css('legalDocument').first + return nil unless ld + + { + body: ld.text, + type: ld['type'] + } + end + end + + def epp_code_map # rubocop:disable Metrics/MethodLength + { + '2302' => [ # Object exists + [:code, :epp_id_taken] + ], + '2305' => [ # Association exists + [:domains, :exist] + ], + '2005' => [ # Value syntax error + [:phone, :invalid], + [:email, :invalid], + [:ident, :invalid] + ] + } + end + + def update_attributes(frame) + return super if frame.blank? + at = {}.with_indifferent_access + at.deep_merge!(self.class.attrs_from(frame.css('chg'))) + super(at) + end + + def attach_legal_document(legal_document_data) + return unless legal_document_data + + legal_documents.build( + document_type: legal_document_data[:type], + body: legal_document_data[:body] + ) + end +end +# rubocop: enable Metrics/ClassLength diff --git a/app/views/admin/contacts/index.haml b/app/views/admin/contacts/index.haml index 7c27cf646..b8704a696 100644 --- a/app/views/admin/contacts/index.haml +++ b/app/views/admin/contacts/index.haml @@ -22,20 +22,20 @@ %thead %tr %th{class: 'col-xs-2'} - = sort_link(@q, 'name', t('name')) + = sort_link(@q, 'name', t(:name)) %th{class: 'col-xs-2'} - = sort_link(@q, 'code', t('code')) + = sort_link(@q, 'ident', t(:identity)) %th{class: 'col-xs-2'} - = sort_link(@q, 'ident', t('identity_code')) + = sort_link(@q, 'email', t(:email)) %th{class: 'col-xs-2'} - = sort_link(@q, 'email', t('email')) + = sort_link(@q, 'code', t(:code)) %tbody - @contacts.each do |x| %tr %td= link_to(x, admin_contact_path(x)) - %td= x.code %td= x.ident %td= x.email + %td= x.code .row .col-md-12 = paginate @contacts diff --git a/app/views/admin/contacts/partials/_address.haml b/app/views/admin/contacts/partials/_address.haml index 1d27ba7bd..eec7e6145 100644 --- a/app/views/admin/contacts/partials/_address.haml +++ b/app/views/admin/contacts/partials/_address.haml @@ -4,25 +4,17 @@ .panel-body - unless @contact.address.nil? %dl.dl-horizontal - %dt= t('country') - %dd= @contact.address.country + %dt= t('street') + %dd= @contact.street %dt= t('city') - %dd= @contact.address.city - - %dt= t('street') - %dd= @contact.address.street - - - if @contact.address.street2 - %dt= t('street') - %dd= @contact.address.street2 - - - if @contact.address.street3 - %dt= t('street') - %dd= @contact.address.street3 - - + %dd= @contact.city %dt= t('zip') - %dd= @contact.address.zip + %dd= @contact.zip + %dt= t('state') + %dd= @contact.state + + %dt= t('country') + %dd= @contact.country diff --git a/app/views/admin/contacts/partials/_general.haml b/app/views/admin/contacts/partials/_general.haml index d5cc42044..512e7cd5d 100644 --- a/app/views/admin/contacts/partials/_general.haml +++ b/app/views/admin/contacts/partials/_general.haml @@ -3,30 +3,28 @@ %h3.panel-title= t('general') .panel-body %dl.dl-horizontal - %dt= t('name') - %dd= @contact.name + %dt= t(:ident) + %dd= @contact.ident + ' [' + @contact.ident_type + ']' - %dt= t('org_name') - %dd= @contact.org_name + %br - %dt= t('code') - %dd= @contact.code - - %dt= t('ident') - %dd= @contact.ident - - %dt= t('ident_type') - %dd= @contact.ident_type - - %dt= t('email') + %dt= t(:email) %dd= @contact.email - %dt= t('phone') + %dt= t(:phone) %dd= @contact.phone + %dt= t(:org_name) + %dd= @contact.org_name + - if @contact.fax - %dt= t('fax') + %dt= t(:fax) %dd= @contact.fax + %br + + %dt= t(:code) + %dd= @contact.code + %dt= t('password') %dd= @contact.auth_info diff --git a/app/views/admin/contacts/show.haml b/app/views/admin/contacts/show.haml index d5620bb7c..8a3e3095a 100644 --- a/app/views/admin/contacts/show.haml +++ b/app/views/admin/contacts/show.haml @@ -1,7 +1,7 @@ .row .col-sm-12 %h2.text-center-xs - = "#{t('contact_details')}" + = @contact.name %hr .row .col-md-6= render 'admin/contacts/partials/general' diff --git a/app/views/epp/contacts/_postal_info.xml.builder b/app/views/epp/contacts/_postal_info.xml.builder index f9c6c5ee9..f84f177c9 100644 --- a/app/views/epp/contacts/_postal_info.xml.builder +++ b/app/views/epp/contacts/_postal_info.xml.builder @@ -1,13 +1,13 @@ -address = @contact.address xml.tag!('contact:postalInfo', type: 'int') do - xml.tag!('contact:name', @contact.name) if @disclosure.try(:[], :name) || @owner - xml.tag!('contact:org', @contact.org_name) if @disclosure.try(:[], :org_name) || @owner - if @disclosure.try(:addr) || @owner + xml.tag!('contact:name', @contact.name) #if @disclosure.try(:[], :name) || @owner + xml.tag!('contact:org', @contact.org_name) #if @disclosure.try(:[], :org_name) || @owner + # if @disclosure.try(:addr) || @owner xml.tag!('contact:addr') do - xml.tag!('contact:street', address.street) if address - xml.tag!('contact:cc', address.country_code) unless address.country_code.nil? - xml.tag!('contact:city', address.city) if address + xml.tag!('contact:street', @contact.street) + xml.tag!('contact:city', @contact.city) + xml.tag!('contact:pc', @contact.zip) + xml.tag!('contact:sp', @contact.state) + xml.tag!('contact:cc', @contact.country_code) end - end + # end end - diff --git a/app/views/epp/contacts/check.xml.builder b/app/views/epp/contacts/check.xml.builder index dab344196..4df3597e3 100644 --- a/app/views/epp/contacts/check.xml.builder +++ b/app/views/epp/contacts/check.xml.builder @@ -6,11 +6,10 @@ xml.epp_head do xml.resData do xml.tag!('contact:chkData', 'xmlns:contact' => 'urn:ietf:params:xml:ns:contact-1.0') do - #xml.tag!('contact:id', @contact.code) - @contacts.each do |contact| + @results.each do |result| xml.tag!('contact:cd') do - xml.tag! "contact:id", contact[:code], avail: contact[:avail] - xml.tag!('contact:reason', contact[:reason]) unless contact[:avail] == 1 + xml.tag! "contact:id", result[:code], avail: result[:avail] + xml.tag!('contact:reason', result[:reason]) unless result[:avail] == 1 end end end diff --git a/app/views/epp/contacts/info.xml.builder b/app/views/epp/contacts/info.xml.builder index 0f4560041..ffe884485 100644 --- a/app/views/epp/contacts/info.xml.builder +++ b/app/views/epp/contacts/info.xml.builder @@ -8,9 +8,9 @@ xml.epp_head do xml.tag!('contact:chkData', 'xmlns:contact' => 'urn:ietf:params:xml:ns:contact-1.0') do xml.tag!('contact:id', @contact.code) xml << render('/epp/contacts/postal_info') - xml.tag!('contact:voice', @contact.phone) if @disclosure.try(:phone) || @owner - xml.tag!('contact:fax', @contact.fax) if @disclosure.try(:fax) || @owner - xml.tag!('contact:email', @contact.email) if @disclosure.try(:email) || @owner + xml.tag!('contact:voice', @contact.phone) #if @disclosure.try(:phone) || @owner + xml.tag!('contact:fax', @contact.fax) #if @disclosure.try(:fax) || @owner + xml.tag!('contact:email', @contact.email) #if @disclosure.try(:email) || @owner xml.tag!('contact:clID', @contact.registrar.try(:name)) xml.tag!('contact:crID', @contact.creator.try(:registrar)) xml.tag!('contact:crDate', @contact.created_at) @@ -19,17 +19,16 @@ xml.epp_head do xml.tag!('contact:upDate', @contact.updated_at) end xml.tag!('contact:ident', @contact.ident, type: @contact.ident_type) - xml.tag!('contact:trDate', '123') if false - if @owner + # xml.tag!('contact:trDate', '123') if false + if can? :view_password, @contact xml.tag!('contact:authInfo') do - xml.tag!('contact:pw', @contact.auth_info) # Doc says we have to return this but is it necessary? + xml.tag!('contact:pw', @contact.auth_info) end end - # statuses - @contact.statuses.each do |cs| - xml.tag!('contact:status', s: cs.value) + @contact.statuses.each do |status| + xml.tag!('contact:status', s: status.value) end - xml << render('/epp/contacts/disclosure_policy') + # xml << render('/epp/contacts/disclosure_policy') end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 5ab4ccef9..64e195c04 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,24 +1,3 @@ -# Files in the config/locales directory are used for internationalization -# and are automatically loaded by Rails. If you want to use locales other -# than English, add the necessary files in this directory. -# -# To use the locales, use `I18n.t`: -# -# I18n.t 'hello' -# -# In views, this is aliased to just `t`: -# -# <%= t('hello') %> -# -# To use a different locale, set it with `I18n.locale`: -# -# I18n.locale = :es -# -# This would use the information in config/locales/es.yml. -# -# To learn more, please read the Rails Internationalization guide -# available at http://guides.rubyonrails.org/i18n.html. - en: views: pagination: @@ -259,7 +238,6 @@ en: unimplemented_command: 'Unimplemented command' domain_exists_but_belongs_to_other_registrar: 'Domain exists but belongs to other registrar' - code: 'Code' value: 'Value' action: 'Action' @@ -321,7 +299,7 @@ en: domain_status_prohibits_deleting: 'Domain status prohibits deleting' domain_deleted: 'Domain deleted!' failed_to_delete_domain: 'Failed to delete domain!' - email: 'Email' + email: 'E-mail' fax: 'Fax' contact_details: 'Contact details' ident: 'Ident' @@ -330,8 +308,8 @@ en: country: 'Country' city: 'City' street: 'Street' - zip: 'Zip' - org_name: 'Organisation name' + zip: 'Postcode' + org_name: 'Org name' failed_to_add_domain: 'Failed to add domain!' domain_added: 'Domain added!' new_contact: 'New contact' @@ -501,3 +479,4 @@ en: address_help: 'Street name, house no - apartment no, city, county, country, zip' download: 'Download' failed_to_create_certificate: 'Failed to create certificate!' + contact_code: Contact code diff --git a/db/migrate/20150212125339_add_state_to_address.rb b/db/migrate/20150212125339_add_state_to_address.rb new file mode 100644 index 000000000..a57412ce6 --- /dev/null +++ b/db/migrate/20150212125339_add_state_to_address.rb @@ -0,0 +1,5 @@ +class AddStateToAddress < ActiveRecord::Migration + def change + add_column :addresses, :state, :string + end +end diff --git a/spec/epp/contact_spec.rb b/spec/epp/contact_spec.rb index 62de51c5a..da6295c6f 100644 --- a/spec/epp/contact_spec.rb +++ b/spec/epp/contact_spec.rb @@ -1,451 +1,411 @@ -# require 'rails_helper' - -# describe 'EPP Contact', epp: true do -# before :all do -# create_settings -# create_disclosure_settings -# @registrar1 = Fabricate(:registrar1) -# @registrar2 = Fabricate(:registrar2) -# @epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345') - -# Fabricate(:api_user, username: 'registrar1', registrar: @registrar1) -# Fabricate(:api_user, username: 'registrar2', registrar: @registrar2) - -# login_as :registrar1 - -# Contact.skip_callback(:create, :before, :generate_code) -# Contact.skip_callback(:create, :before, :generate_auth_info) -# end - -# after :all do -# Contact.set_callback(:create, :before, :generate_code) -# Contact.set_callback(:create, :before, :generate_auth_info) -# end - -# context 'with valid user' do -# context 'create command' do -# it 'fails if request xml is missing' do -# xml = @epp_xml.create -# response = epp_plain_request(xml, :xml) -# response[:results][0][:msg].should == 'Command syntax error' -# response[:results][0][:result_code].should == '2001' - -# response[:results].count.should == 1 -# end - -# it 'fails if request xml is missing' do -# xml = @epp_xml.create( -# postalInfo: { addr: { value: nil } } -# ) -# response = epp_plain_request(xml, :xml) -# response[:results][0][:msg].should == 'Required parameter missing: name' -# response[:results][1][:msg].should == 'Required parameter missing: city' -# response[:results][2][:msg].should == 'Required parameter missing: cc' -# response[:results][3][:msg].should == 'Required parameter missing: ident' -# response[:results][4][:msg].should == 'Required parameter missing: voice' -# response[:results][5][:msg].should == 'Required parameter missing: email' - -# response[:results][0][:result_code].should == '2003' -# response[:results][1][:result_code].should == '2003' -# response[:results][2][:result_code].should == '2003' -# response[:results][3][:result_code].should == '2003' -# response[:results][4][:result_code].should == '2003' -# response[:results][5][:result_code].should == '2003' - -# response[:results].count.should == 6 -# end - -# it 'successfully saves ident type' do -# xml = { ident: { value: '1990-22-12', attrs: { type: 'birthday' } } } -# epp_plain_request(create_contact_xml(xml), :xml) - -# Contact.last.ident_type.should == 'birthday' -# end - -# it 'successfully creates a contact' do -# response = epp_plain_request(create_contact_xml, :xml) - -# response[:msg].should == 'Command completed successfully' -# response[:result_code].should == '1000' - -# @contact = Contact.last - -# @contact.registrar.should == @registrar1 -# # registrar1.api_users.should include(@contact.created_by) -# # @contact.updated_by_id.should == nil -# @contact.ident.should == '37605030299' -# @contact.address.street.should == '123 Example' - -# log = ApiLog::EppLog.last -# log.request_command.should == 'create' -# log.request_object.should == 'contact' -# log.request_successful.should == true -# log.api_user_name.should == '1-api-registrar1' -# log.api_user_registrar.should == 'registrar1' -# end - -# it 'successfully adds registrar' do -# response = epp_plain_request(create_contact_xml, :xml) - -# response[:msg].should == 'Command completed successfully' -# response[:result_code].should == '1000' - -# Contact.last.registrar.should == @registrar1 -# end - -# it 'returns result data upon success' do -# response = epp_plain_request(create_contact_xml, :xml) - -# response[:msg].should == 'Command completed successfully' -# response[:result_code].should == '1000' - -# id = response[:parsed].css('resData creData id').first -# cr_date = response[:parsed].css('resData creData crDate').first - -# id.text.length.should == 8 -# # 5 seconds for what-ever weird lag reasons might happen -# cr_date.text.to_time.should be_within(5).of(Time.now) -# end - -# it 'creates disclosure data' do -# xml = { -# disclose: { value: { -# voice: { value: '' }, -# addr: { value: '' }, -# name: { value: '' }, -# org_name: { value: '' }, -# email: { value: '' }, -# fax: { value: '' } -# }, attrs: { flag: '1' } -# } -# } - -# response = epp_plain_request(create_contact_xml(xml), :xml) -# response[:result_code].should == '1000' - -# @contact = Contact.last -# @contact.disclosure.name.should == true -# @contact.disclosure.org_name.should == true -# @contact.disclosure.phone.should == true -# @contact.disclosure.fax.should == true -# @contact.disclosure.email.should == true -# @contact.disclosure.address.should == true -# end - -# it 'creates disclosure data merging with defaults' do -# xml = { -# disclose: { value: { -# voice: { value: '' }, -# addr: { value: '' } -# }, attrs: { flag: '1' } -# } -# } - -# response = epp_plain_request(create_contact_xml(xml), :xml) -# response[:result_code].should == '1000' - -# @contact = Contact.last -# @contact.disclosure.name.should == nil -# @contact.disclosure.org_name.should == nil -# @contact.disclosure.phone.should == true -# @contact.disclosure.fax.should == nil -# @contact.disclosure.email.should == nil -# @contact.disclosure.address.should == true -# end -# end - -# context 'update command' do -# before :all do -# @contact = -# Fabricate( -# :contact, -# # created_by_id: 1, -# registrar: @registrar1, -# email: 'not_updated@test.test', -# code: 'sh8013', -# auth_info: 'password' -# ) -# end - -# it 'fails if request is invalid' do -# xml = @epp_xml.update -# response = epp_plain_request(xml, :xml) # epp_request('contacts/update_missing_attr.xml') - -# response[:results][0][:result_code].should == '2003' -# response[:results][0][:msg].should == 'Required parameter missing: add, rem or chg' -# response[:results][1][:result_code].should == '2003' -# response[:results][1][:msg].should == 'Required parameter missing: id' -# response[:results].count.should == 2 -# end - -# it 'fails with wrong authentication info' do -# login_as :registrar2 do -# response = epp_plain_request(update_contact_xml({ id: { value: 'sh8013' } }), :xml) -# expect(response[:msg]).to eq('Authorization error') -# expect(response[:result_code]).to eq('2201') -# end -# end - -# it 'is succesful' do -# response = epp_plain_request(update_contact_xml({ id: { value: 'sh8013' } }), :xml) - -# response[:msg].should == 'Command completed successfully' -# @contact.reload -# @contact.name.should == 'John Doe Edited' -# @contact.email.should == 'edited@example.example' -# end - -# it 'returns phone and email error' do -# xml = { -# id: { value: 'sh8013' }, -# chg: { -# voice: { value: '123213' }, -# email: { value: 'aaa' } -# } -# } - -# response = epp_plain_request(update_contact_xml(xml), :xml) - -# response[:results][0][:msg].should == 'Phone nr is invalid' -# response[:results][0][:result_code].should == '2005' - -# response[:results][1][:msg].should == 'Email is invalid' -# response[:results][1][:result_code].should == '2005' -# end - -# it 'updates disclosure items' do -# Fabricate( -# :contact, -# code: 'sh8013disclosure', -# auth_info: '2fooBAR', -# registrar: @registrar1, -# # created_by_id: ApiUser.first.id, -# disclosure: Fabricate(:contact_disclosure, phone: true, email: true)) - -# xml = { -# id: { value: 'sh8013disclosure' }, -# authInfo: { pw: { value: '2fooBAR' } } -# } -# @response = epp_plain_request(update_contact_xml(xml), :xml) - -# @response[:results][0][:msg].should == 'Command completed successfully' -# @response[:results][0][:result_code].should == '1000' - -# Contact.last.disclosure.phone.should == false -# Contact.last.disclosure.email.should == false -# end -# end - -# context 'delete command' do -# it 'fails if request is invalid' do -# xml = @epp_xml.delete({ uid: { value: '23123' } }) -# response = epp_plain_request(xml, :xml) - -# response[:results][0][:msg].should == 'Required parameter missing: id' -# response[:results][0][:result_code].should == '2003' -# response[:results].count.should == 1 -# end - -# it 'deletes contact' do -# @contact_deleted = -# # Fabricate(:contact, code: 'dwa1234', created_by_id: ApiUser.first.id, registrar: registrar1) -# Fabricate(:contact, code: 'dwa1234', registrar: @registrar1) - -# response = epp_plain_request(delete_contact_xml({ id: { value: 'dwa1234' } }), :xml) -# response[:msg].should == 'Command completed successfully' -# response[:result_code].should == '1000' -# response[:clTRID].should == 'ABC-12345' - -# Contact.find_by_id(@contact_deleted.id).should == nil -# end - -# it 'returns error if obj doesnt exist' do -# response = epp_plain_request(delete_contact_xml, :xml) -# response[:msg].should == 'Object does not exist' -# response[:result_code].should == '2303' -# end - -# it 'fails if contact has associated domain' do -# Fabricate( -# :domain, -# registrar: @registrar1, -# owner_contact: Fabricate( -# :contact, -# code: 'dwa1234', -# # created_by_id: registrar1.id, -# registrar: @registrar1) -# ) -# Domain.last.owner_contact.address.present?.should == true -# response = epp_plain_request(delete_contact_xml({ id: { value: 'dwa1234' } }), :xml) - -# response[:msg].should == 'Object association prohibits operation' -# response[:result_code].should == '2305' - -# Domain.last.owner_contact.present?.should == true -# end -# end - -# context 'check command' do -# it 'fails if request is invalid' do -# xml = @epp_xml.check({ uid: { value: '123asde' } }) -# response = epp_plain_request(xml, :xml) - -# response[:results][0][:msg].should == 'Required parameter missing: id' -# response[:results][0][:result_code].should == '2003' -# response[:results].count.should == 1 -# end - -# it 'returns info about contact availability' do -# Fabricate(:contact, code: 'check-1234') - -# response = epp_plain_request(check_multiple_contacts_xml, :xml) - -# response[:msg].should == 'Command completed successfully' -# response[:result_code].should == '1000' -# ids = response[:parsed].css('resData chkData id') - -# ids[0].attributes['avail'].text.should == '0' -# ids[1].attributes['avail'].text.should == '1' - -# ids[0].text.should == 'check-1234' -# ids[1].text.should == 'check-4321' -# end -# end - -# # context 'info command' do -# # before :all do -# # @registrar1_contact = Fabricate(:contact, code: 'info-4444', registrar: @registrar1, -# # name: 'Johnny Awesome', address: Fabricate(:address)) -# # end - -# # fit 'return info about contact' do -# # login_as :registrar2 do -# # xml = @epp_xml.info(id: { value: @registrar1_contact.code }) -# # response = epp_plain_request(xml, :xml) -# # response[:msg].should == 'Command completed successfully' -# # response[:result_code].should == '1000' - -# # contact = response[:parsed].css('resData chkData') -# # contact.css('name').first.text.should == 'Johnny Awesome' -# # end -# # end - -# # it 'fails if request invalid' do -# # response = epp_plain_request(@epp_xml.info({ wrongid: { value: '123123' } }), :xml) -# # response[:results][0][:msg].should == 'Required parameter missing: id' -# # response[:results][0][:result_code].should == '2003' -# # response[:results].count.should == 1 -# # end - -# # it 'returns error when object does not exist' do -# # response = epp_plain_request(info_contact_xml({ id: { value: 'no-contact' } }), :xml) -# # response[:msg].should == 'Object does not exist' -# # response[:result_code].should == '2303' -# # response[:results][0][:value].should == 'no-contact' -# # end - -# # # it 'returns auth error for non-owner with wrong password' do -# # # @contact = Fabricate(:contact, -# # # registrar: registrar2, code: 'info-4444', name: 'Johnny Awesome', auth_info: 'asde', -# # # address: Fabricate(:address), disclosure: Fabricate(:contact_disclosure, name: false)) - -# # # xml = @epp_xml.info({ id: { value: @contact.code }, authInfo: { pw: { value: 'asdesde' } } }) -# # # response = epp_plain_request(xml, :xml, :registrar1) - -# # # expect(response[:result_code]).to eq('2200') -# # # expect(response[:msg]).to eq('Authentication error') -# # # end - -# # context 'about disclose' do -# # it 'discloses items with wrong password when queried by owner' do -# # @contact = Fabricate(:contact, -# # registrar: registrar1, code: 'info-4444', -# # name: 'Johnny Awesome', auth_info: 'asde', -# # address: Fabricate(:address), disclosure: Fabricate(:contact_disclosure, name: false)) - -# # xml = @epp_xml.info({ id: { value: @contact.code } }) -# # login_as :registrar1 do -# # response = epp_plain_request(xml, :xml) -# # contact = response[:parsed].css('resData chkData') - -# # expect(response[:result_code]).to eq('1000') -# # expect(response[:msg]).to eq('Command completed successfully') -# # expect(contact.css('name').first.text).to eq('Johnny Awesome') -# # end -# # end - -# # it 'doesn\'t disclose items to non-owner with right password' do -# # @contact = Fabricate(:contact, registrar: registrar2, code: 'info-4444', -# # name: 'Johnny Awesome', auth_info: 'password', -# # address: Fabricate(:address), disclosure: Fabricate(:contact_disclosure, name: false)) - -# # xml = @epp_xml.info({ id: { value: @contact.code }, authInfo: { pw: { value: 'password' } } }) -# # response = epp_plain_request(xml, :xml, :registrar1) -# # contact = response[:parsed].css('resData chkData') - -# # expect(response[:result_code]).to eq('1000') -# # expect(response[:msg]).to eq('Command completed successfully') -# # expect(contact.css('chkData postalInfo name').first).to eq(nil) -# # end - -# # it 'discloses items to owner' do -# # @contact = Fabricate(:contact, registrar: registrar1, code: 'info-4444', name: 'Johnny Awesome', -# # auth_info: 'password', -# # address: Fabricate(:address), disclosure: Fabricate(:contact_disclosure, name: false)) - -# # xml = @epp_xml.info({ id: { value: @contact.code } }) -# # response = epp_plain_request(xml, :xml, :registrar1) -# # contact = response[:parsed].css('resData chkData') - -# # expect(response[:result_code]).to eq('1000') -# # expect(response[:msg]).to eq('Command completed successfully') -# # expect(contact.css('name').first.text).to eq('Johnny Awesome') -# # end - -# # it 'doesn\'t disclose private elements' do -# # Fabricate(:contact, code: 'info-4444', auth_info: '2fooBAR', registrar: registrar2, -# # disclosure: Fabricate(:contact_disclosure, name: true, email: false, phone: false)) - -# # xml = @epp_xml.info({ id: { value: 'info-4444' }, authInfo: { pw: { value: '2fooBAR' } } }) - -# # response = epp_plain_request(xml, :xml, :registrar1) -# # contact = response[:parsed].css('resData chkData') - -# # expect(response[:result_code]).to eq('1000') - -# # expect(contact.css('chkData phone')).to eq(contact.css('chkData disclose phone')) -# # expect(contact.css('chkData phone').count).to eq(1) -# # expect(contact.css('chkData email')).to eq(contact.css('chkData disclose email')) -# # expect(contact.css('chkData email').count).to eq(1) -# # expect(contact.css('postalInfo name').present?).to be(true) -# # end -# # end - -# # it 'does not display unassociated object without password' do -# # xml = @epp_xml.info(id: { value: @registrar1_contact.code }) -# # response = epp_plain_request(xml, :xml, :registrar2) -# # expect(response[:result_code]).to eq('2003') -# # expect(response[:msg]).to eq('Required parameter missing: pw') -# # end - -# # it 'does not display unassociated object with wrong password' do -# # login_as :registrar2 -# # xml = @epp_xml.info(id: { value: @registrar1_contact.code }, -# # authInfo: { pw: { value: 'wrong-pw' } }) -# # response = epp_plain_request(xml, :xml) - -# # response[:msg].should == 'Authentication error' -# # response[:result_code].should == '2200' -# # end -# # end - -# context 'renew command' do -# it 'returns 2101-unimplemented command' do -# response = epp_plain_request('contacts/renew.xml') - -# response[:msg].should == 'Unimplemented command' -# response[:result_code].should == '2101' -# end -# end -# end -# end +require 'rails_helper' + +describe 'EPP Contact', epp: true do + before :all do + create_settings + create_disclosure_settings + @registrar1 = Fabricate(:registrar1) + @registrar2 = Fabricate(:registrar2) + @epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345') + + Fabricate(:api_user, username: 'registrar1', registrar: @registrar1) + Fabricate(:api_user, username: 'registrar2', registrar: @registrar2) + + login_as :registrar1 + + Contact.skip_callback(:create, :before, :generate_code) + Contact.skip_callback(:create, :before, :generate_auth_info) + + @contact = Fabricate(:contact, registrar: @registrar1) + end + + after :all do + Contact.set_callback(:create, :before, :generate_code) + Contact.set_callback(:create, :before, :generate_auth_info) + end + + context 'with valid user' do + context 'create command' do + def create_request(overwrites = {}) + defaults = { + postalInfo: { + name: { value: 'John Doe' }, + addr: { + street: { value: '123 Example' }, + city: { value: 'Tallinn' }, + cc: { value: 'EE' } + } + }, + voice: { value: '+372.1234567' }, + email: { value: 'test@example.example' }, + ident: { value: '37605030299', attrs: { type: 'priv' } } + } + create_xml = @epp_xml.create(defaults.deep_merge(overwrites)) + epp_plain_request(create_xml, :xml) + end + + it 'fails if request xml is missing' do + response = epp_plain_request(@epp_xml.create, :xml) + response[:results][0][:msg].should == + 'Required parameter missing: create > create > postalInfo > name' + response[:results][1][:msg].should == + 'Required parameter missing: create > create > postalInfo > addr > city' + response[:results][2][:msg].should == + 'Required parameter missing: create > create > postalInfo > addr > cc' + response[:results][3][:msg].should == + 'Required parameter missing: create > create > ident' + response[:results][4][:msg].should == + 'Required parameter missing: create > create > voice' + response[:results][5][:msg].should == + 'Required parameter missing: create > create > email' + + response[:results][0][:result_code].should == '2003' + response[:results][1][:result_code].should == '2003' + response[:results][2][:result_code].should == '2003' + response[:results][3][:result_code].should == '2003' + response[:results][4][:result_code].should == '2003' + response[:results][5][:result_code].should == '2003' + + response[:results].count.should == 6 + end + + it 'successfully creates a contact' do + response = create_request + + response[:msg].should == 'Command completed successfully' + response[:result_code].should == '1000' + + @contact = Contact.last + + @contact.registrar.should == @registrar1 + @registrar1.api_users.should include(@contact.creator) + @contact.ident.should == '37605030299' + @contact.address.street.should == '123 Example' + + log = ApiLog::EppLog.last + log.request_command.should == 'create' + log.request_object.should == 'contact' + log.request_successful.should == true + log.api_user_name.should == '1-api-registrar1' + log.api_user_registrar.should == 'registrar1' + end + + it 'successfully saves ident type' do + response = create_request( + { ident: { value: '1990-22-12', attrs: { type: 'birthday' } } } + ) + + response[:msg].should == 'Command completed successfully' + response[:result_code].should == '1000' + + Contact.last.ident_type.should == 'birthday' + end + + it 'successfully adds registrar' do + response = create_request + + response[:msg].should == 'Command completed successfully' + response[:result_code].should == '1000' + + Contact.last.registrar.should == @registrar1 + end + + it 'returns result data upon success' do + response = create_request + + response[:msg].should == 'Command completed successfully' + response[:result_code].should == '1000' + + id = response[:parsed].css('resData creData id').first + cr_date = response[:parsed].css('resData creData crDate').first + + id.text.length.should == 8 + # 5 seconds for what-ever weird lag reasons might happen + cr_date.text.to_time.should be_within(5).of(Time.now) + end + end + + context 'update command' do + before :all do + @contact = + Fabricate( + :contact, + # created_by_id: 1, + registrar: @registrar1, + email: 'not_updated@test.test', + code: 'sh8013', + auth_info: 'password' + ) + end + + def update_request(overwrites = {}) + defaults = { + id: { value: 'asd123123er' }, + authInfo: { pw: { value: 'password' } }, + chg: { + postalInfo: { + name: { value: 'John Doe Edited' } + }, + voice: { value: '+372.7654321' }, + email: { value: 'edited@example.example' }, + disclose: { + value: { + voice: { value: '' }, + email: { value: '' } + }, attrs: { flag: '0' } + } + } + } + update_xml = @epp_xml.update(defaults.deep_merge(overwrites)) + epp_plain_request(update_xml, :xml) + end + + it 'fails if request is invalid' do + response = epp_plain_request(@epp_xml.update, :xml) + + response[:results][0][:msg].should == + 'Required parameter missing: add, rem or chg' + response[:results][0][:result_code].should == '2003' + response[:results][1][:msg].should == + 'Required parameter missing: update > update > id' + response[:results][1][:result_code].should == '2003' + response[:results][2][:msg].should == + 'Required parameter missing: update > update > authInfo > pw' + response[:results][2][:result_code].should == '2003' + response[:results].count.should == 3 + end + + it 'returns error if obj doesnt exist' do + response = update_request({ id: { value: 'not-exists' } }) + response[:msg].should == 'Object does not exist' + response[:result_code].should == '2303' + response[:results].count.should == 1 + end + + it 'is succesful' do + response = update_request({ id: { value: 'sh8013' } }) + + response[:msg].should == 'Command completed successfully' + @contact.reload + @contact.name.should == 'John Doe Edited' + @contact.email.should == 'edited@example.example' + end + + it 'fails with wrong authentication info' do + login_as :registrar2 do + response = update_request({ id: { value: 'sh8013' } }) + response[:msg].should == 'Authorization error' + response[:result_code].should == '2201' + end + end + + it 'returns phone and email error' do + response = update_request({ + id: { value: 'sh8013' }, + chg: { + voice: { value: '123213' }, + email: { value: 'wrong' } + } + }) + + response[:results][0][:msg].should == 'Phone nr is invalid' + response[:results][0][:result_code].should == '2005' + response[:results][1][:msg].should == 'Email is invalid' + response[:results][1][:result_code].should == '2005' + end + end + + context 'delete command' do + before do + @contact = Fabricate(:contact, registrar: @registrar1) + end + + def delete_request(overwrites = {}) + defaults = { + id: { value: @contact.code }, + authInfo: { pw: { value: @contact.auth_info } } + } + delete_xml = @epp_xml.delete(defaults.deep_merge(overwrites)) + epp_plain_request(delete_xml, :xml) + end + + it 'fails if request is invalid' do + response = epp_plain_request(@epp_xml.delete, :xml) + + response[:results][0][:msg].should == + 'Required parameter missing: delete > delete > id' + response[:results][0][:result_code].should == '2003' + response[:results][1][:msg].should == + 'Required parameter missing: delete > delete > authInfo > pw' + response[:results][1][:result_code].should == '2003' + response[:results].count.should == 2 + end + + it 'returns error if obj doesnt exist' do + response = delete_request({ id: { value: 'not-exists' } }) + response[:msg].should == 'Object does not exist' + response[:result_code].should == '2303' + response[:results].count.should == 1 + end + + it 'deletes contact' do + response = delete_request + response[:msg].should == 'Command completed successfully' + response[:result_code].should == '1000' + response[:clTRID].should == 'ABC-12345' + + Contact.find_by_id(@contact.id).should == nil + end + + it 'fails if contact has associated domain' do + @domain = Fabricate(:domain, registrar: @registrar1, owner_contact: @contact) + @domain.owner_contact.address.present?.should == true + + response = delete_request + response[:msg].should == 'Object association prohibits operation' + response[:result_code].should == '2305' + response[:results].count.should == 1 + + @domain.owner_contact.present?.should == true + end + + it 'fails with wrong authentication info' do + login_as :registrar2 do + response = delete_request + response[:msg].should == 'Authorization error' + response[:result_code].should == '2201' + response[:results].count.should == 1 + end + end + end + + context 'check command' do + def check_request(overwrites = {}) + defaults = { + id: { value: @contact.code }, + authInfo: { pw: { value: @contact.auth_info } } + } + xml = @epp_xml.check(defaults.deep_merge(overwrites)) + epp_plain_request(xml, :xml) + end + + it 'fails if request is invalid' do + response = epp_plain_request(@epp_xml.check, :xml) + + response[:results][0][:msg].should == 'Required parameter missing: check > check > id' + response[:results][0][:result_code].should == '2003' + response[:results].count.should == 1 + end + + it 'returns info about contact availability' do + Fabricate(:contact, code: 'check-1234') + + response = epp_plain_request(check_multiple_contacts_xml, :xml) + + response[:msg].should == 'Command completed successfully' + response[:result_code].should == '1000' + ids = response[:parsed].css('resData chkData id') + + ids[0].attributes['avail'].text.should == '0' + ids[1].attributes['avail'].text.should == '1' + + ids[0].text.should == 'check-1234' + ids[1].text.should == 'check-4321' + end + end + + context 'info command' do + before :all do + @registrar1_contact = Fabricate( + :contact, code: 'info-4444', registrar: @registrar1, + name: 'Johnny Awesome', address: Fabricate(:address)) + end + + def info_request(overwrites = {}) + defaults = { + id: { value: @contact.code }, + authInfo: { pw: { value: @contact.auth_info } } + } + xml = @epp_xml.info(defaults.deep_merge(overwrites)) + epp_plain_request(xml, :xml) + end + + it 'fails if request invalid' do + response = epp_plain_request(@epp_xml.info, :xml) + response[:results][0][:msg].should == + 'Required parameter missing: info > info > id' + response[:results][0][:result_code].should == '2003' + response[:results].count.should == 1 + end + + it 'returns error when object does not exist' do + response = info_request({ id: { value: 'no-contact' } }) + response[:msg].should == 'Object does not exist' + response[:result_code].should == '2303' + response[:results][0][:value].should == 'no-contact' + response[:results].count.should == 1 + end + + it 'return info about contact' do + response = info_request({ id: { value: @registrar1_contact.code } }) + response[:msg].should == 'Command completed successfully' + response[:result_code].should == '1000' + + contact = response[:parsed].css('resData chkData') + contact.css('name').first.text.should == 'Johnny Awesome' + end + + it 'returns no authorization error for wrong password when owner' do + response = info_request({ authInfo: { pw: { value: 'wrong-pw' } } }) + + response[:msg].should == 'Command completed successfully' + response[:result_code].should == '1000' + response[:results].count.should == 1 + end + + it 'returns no authorization error for wrong user but correct pw' do + login_as :registrar2 do + response = info_request + + response[:msg].should == 'Command completed successfully' + response[:result_code].should == '1000' + response[:results].count.should == 1 + end + end + + it 'returns authorization error for wrong user and wrong pw' do + login_as :registrar2 do + response = info_request({ authInfo: { pw: { value: 'wrong-pw' } } }) + response[:msg].should == 'Authorization error' + response[:result_code].should == '2201' + response[:results].count.should == 1 + end + end + end + + context 'renew command' do + it 'returns 2101-unimplemented command' do + response = epp_plain_request('contacts/renew.xml') + + response[:msg].should == 'Unimplemented command' + response[:result_code].should == '2101' + end + end + end + + def check_multiple_contacts_xml + ' + + + + + check-1234 + check-4321 + + + ABC-12345 + + ' + end +end diff --git a/spec/epp/domain_spec.rb b/spec/epp/domain_spec.rb index 5ba4c4159..90f574fab 100644 --- a/spec/epp/domain_spec.rb +++ b/spec/epp/domain_spec.rb @@ -206,8 +206,16 @@ describe 'EPP Domain', epp: true do it 'does not create domain without nameservers' do xml = domain_create_xml(ns: []) response = epp_plain_request(xml, :xml) - response[:result_code].should == '2003' - response[:msg].should == 'Required parameter missing: create > create > ns > hostAttr' + + response[:results][0][:msg].should == + 'Required parameter missing: create > create > ns' + response[:results][0][:result_code].should == '2003' + + response[:results][1][:msg].should == + 'Required parameter missing: create > create > ns > hostAttr' + response[:results][1][:result_code].should == '2003' + + response[:results].count.should == 2 end it 'does not create domain with too many nameservers' do @@ -294,8 +302,8 @@ describe 'EPP Domain', epp: true do xml = domain_create_xml(period_value: 365, period_unit: 'd') response = epp_plain_request(xml, :xml) - response[:result_code].should == '1000' response[:msg].should == 'Command completed successfully' + response[:result_code].should == '1000' Domain.first.valid_to.should == Date.today + 1.year end diff --git a/spec/fabricators/domain_fabricator.rb b/spec/fabricators/domain_fabricator.rb index d6197b6e4..fd5c209e6 100644 --- a/spec/fabricators/domain_fabricator.rb +++ b/spec/fabricators/domain_fabricator.rb @@ -1,5 +1,5 @@ Fabricator(:domain) do - name { "#{Faker::Internet.domain_word}.ee" } + name { "fabricate_name#{rand(1_000_000)}.ee" } valid_to Date.new(2014, 8, 7) period 1 period_unit 'y' diff --git a/spec/models/contact_disclosure_spec.rb b/spec/models/contact_disclosure_spec.rb deleted file mode 100644 index f8c268fca..000000000 --- a/spec/models/contact_disclosure_spec.rb +++ /dev/null @@ -1,91 +0,0 @@ -require 'rails_helper' - -describe ContactDisclosure do - it { should belong_to(:contact) } - - context 'about class' do - it 'should have versioning enabled?' do - ContactDisclosure.paper_trail_enabled_for_model?.should == true - end - - it 'should have custom log prexied table name for versions table' do - ContactDisclosureVersion.table_name.should == 'log_contact_disclosures' - end - end - - context 'with invalid attribute' do - before :all do - @contact_disclosure = ContactDisclosure.new - end - - it 'should not be valid' do - @contact_disclosure.valid? - @contact_disclosure.errors.full_messages.should match_array([ - ]) - end - - it 'should not have any versions' do - @contact_disclosure.versions.should == [] - end - end - - context 'with valid attributes' do - before :all do - @contact_disclosure = Fabricate(:contact_disclosure) - end - - it 'should be valid' do - @contact_disclosure.valid? - @contact_disclosure.errors.full_messages.should match_array([]) - end - - it 'should be valid twice' do - @contact_disclosure = Fabricate(:contact_disclosure) - @contact_disclosure.valid? - @contact_disclosure.errors.full_messages.should match_array([]) - end - - it 'should have one version' do - with_versioning do - @contact_disclosure.versions.should == [] - @contact_disclosure.name = false - @contact_disclosure.save - @contact_disclosure.errors.full_messages.should match_array([]) - @contact_disclosure.versions.size.should == 1 - end - end - end - -end - -describe '.extract_attributes' do - it 'should return empty hash for empty arguments' do - result = ContactDisclosure.extract_attributes(Nokogiri::XML::Document.new) - expect(result).to eq({}) - end - - it 'should return empty hash if no disclosure' do - parsed_frame = Nokogiri::XML(create_contact_xml).remove_namespaces! - result = ContactDisclosure.extract_attributes(parsed_frame) - expect(result).to eq({}) - end - - # TODO: remodel create contact xml to support disclosure - it 'should return disclosure has if disclosure' do - epp_xml = EppXml::Contact.new - xml = epp_xml.create( - { - disclose: { value: { - voice: { value: '' }, - addr: { value: '' }, - name: { value: '' }, - org_name: { value: '' }, - email: { value: '' }, - fax: { value: '' } - }, attrs: { flag: '0' } - } }) - parsed_frame = Nokogiri::XML(xml).remove_namespaces! - result = ContactDisclosure.extract_attributes(parsed_frame) - expect(result).to eq({ phone: '0', email: '0', fax: '0', address: '0', name: '0', org_name: '0' }) - end -end diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb index 58b54cacf..d05d0d40c 100644 --- a/spec/models/contact_spec.rb +++ b/spec/models/contact_spec.rb @@ -39,11 +39,11 @@ describe Contact do end it 'should not have creator' do - @contact.cr_id.should == nil + @contact.creator.should == nil end it 'should not have updater' do - @contact.up_id.should == nil + @contact.updator.should == nil end it 'phone should return false' do @@ -179,57 +179,18 @@ describe Contact do end context 'with creator' do - before :all do - # @contact.created_by = @api_user - end - - # TODO: change cr_id to something else it 'should return username of creator' do - # @contact.cr_id.should == 'gitlab' - end - end - - context 'with updater' do - before :all do - # @contact.updated_by = @api_user + # @contact.creator_str.should == 'gitlab' end - # TODO: change up_id to something else it 'should return username of updater' do - # @contact.up_id.should == 'gitlab' + # @contact.updator.should == 'gitlab' end - end end end end -# TODO: investigate it a bit more -# describe Contact, '#relations_with_domain?' do -# context 'with relation' do -# before :all do -# create_settings -# Fabricate(:domain) -# @contact = Fabricate(:contact) -# end - -# it 'should have relation with domain' do -# @contact.relations_with_domain?.should == true -# end -# end -# end - -describe Contact, '.extract_params' do - it 'returns params hash'do - ph = { id: '123123', email: 'jdoe@example.com', authInfo: { pw: 'asde' }, - postalInfo: { name: 'fred', addr: { cc: 'EE' } } } - Contact.extract_attributes(ph).should == { - name: 'fred', - email: 'jdoe@example.com' - } - end -end - describe Contact, '.check_availability' do before do Fabricate(:contact, code: 'asd12') diff --git a/spec/support/epp.rb b/spec/support/epp.rb index 3bceb034d..35b24a942 100644 --- a/spec/support/epp.rb +++ b/spec/support/epp.rb @@ -112,7 +112,7 @@ module Epp end def next_domain_name - "example#{@uniq_no.call}.ee" + "example#{rand(100000000)}.ee" end ### REQUEST TEMPLATES ### diff --git a/spec/support/epp_contact_xml_helper.rb b/spec/support/epp_contact_xml_helper.rb deleted file mode 100644 index 693e12ae7..000000000 --- a/spec/support/epp_contact_xml_helper.rb +++ /dev/null @@ -1,87 +0,0 @@ -module EppContactXmlHelper - def create_contact_xml(xml_params = {}) - defaults = { - postalInfo: { - name: { value: 'John Doe' }, - addr: { - street: { value: '123 Example' }, - city: { value: 'Tallinn' }, - cc: { value: 'EE' } - } - }, - voice: { value: '+372.1234567' }, - email: { value: 'test@example.example' }, - ident: { value: '37605030299', attrs: { type: 'op' } } - } - - xml_params = defaults.deep_merge(xml_params) - epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345') - epp_xml.create(xml_params) - end - - def update_contact_xml(xml_params = {}) - defaults = { - id: { value: 'asd123123er' }, - authInfo: { pw: { value: 'password' } }, - chg: { - postalInfo: { - name: { value: 'John Doe Edited' } - }, - voice: { value: '+372.7654321' }, - email: { value: 'edited@example.example' }, - disclose: { - value: { - voice: { value: '' }, - email: { value: '' } - }, attrs: { flag: '0' } - } - } - } - xml_params = defaults.deep_merge(xml_params) - epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345') - epp_xml.update(xml_params) - end - - def delete_contact_xml(xml_params = {}) - defaults = { id: { value: 'sh8012' } } - xml_params = defaults.deep_merge(xml_params) - epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345') - epp_xml.delete(xml_params) - end - - def info_contact_xml(xml_params = {}) - defaults = { id: { value: 'sh8012' }, authInfo: { pw: { value: 'password' } } } - xml_params = defaults.deep_merge(xml_params) - epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345') - epp_xml.info(xml_params) - end - - def check_contact_xml(xml_params = {}) - defaults = { - id: { value: 'ad123c3' } - } - xml_params = defaults.deep_merge(xml_params) - epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345') - epp_xml.check(xml_params) - end - - def check_multiple_contacts_xml - ' - - - - - check-1234 - check-4321 - - - ABC-12345 - - ' - end -end - -RSpec.configure do |c| - c.include EppContactXmlHelper -end