From d1ec91323b24b98e941a4dd4e5fa39eea38fa3ba Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Tue, 10 Mar 2015 10:57:10 +0200 Subject: [PATCH] Start refactoring rights to cancan --- app/controllers/epp/domains_controller.rb | 168 ++--------- app/models/ability.rb | 3 + app/models/epp/epp_domain.rb | 331 ++-------------------- spec/epp/domain_spec.rb | 4 +- spec/models/epp_domain_spec.rb | 83 ------ 5 files changed, 50 insertions(+), 539 deletions(-) diff --git a/app/controllers/epp/domains_controller.rb b/app/controllers/epp/domains_controller.rb index 28930ba8d..b936125f8 100644 --- a/app/controllers/epp/domains_controller.rb +++ b/app/controllers/epp/domains_controller.rb @@ -1,10 +1,11 @@ class Epp::DomainsController < EppController skip_authorization_check # TODO: remove it + before_action :find_domain, only: [:info] + before_action :find_password, only: [:info] + def create @domain = Epp::EppDomain.new_from_epp(params[:parsed_frame], current_user) - # @domain.parse_and_attach_domain_dependencies(params[:parsed_frame]) - # @domain.parse_and_attach_ds_data(params[:parsed_frame].css('extension create')) if @domain.errors.any? || !@domain.save handle_errors(@domain) @@ -14,8 +15,7 @@ class Epp::DomainsController < EppController end def info - @domain = find_domain - handle_errors(@domain) and return unless @domain + authorize! :info, @domain, @password render_epp_response '/epp/domains/info' end @@ -44,14 +44,6 @@ class Epp::DomainsController < EppController handle_errors(@domain) and return unless @domain - # @domain.parse_and_detach_domain_dependencies(params[:parsed_frame].css('rem') - # @domain.parse_and_detach_ds_data(params[:parsed_frame].css('extension rem')) - # @domain.parse_and_attach_domain_dependencies(params[:parsed_frame].css('add')) - # @domain.parse_and_attach_ds_data(params[:parsed_frame].css('extension add')) - # @domain.parse_and_update_domain_dependencies(params[:parsed_frame].css('chg')) - # @domain.attach_legal_document(Epp::EppDomain.parse_legal_document_from_frame(params[:parsed_frame])) - # binding.pry - if @domain.update(params[:parsed_frame], current_user) render_epp_response '/epp/domains/success' else @@ -63,7 +55,7 @@ class Epp::DomainsController < EppController # rubocop: disable Metrics/MethodLength def transfer - @domain = find_domain(secure: false) + @domain = find_domain handle_errors(@domain) and return unless @domain handle_errors(@domain) and return unless @domain.authenticate(domain_transfer_params[:pw]) @@ -197,119 +189,6 @@ class Epp::DomainsController < EppController } end - def domain_create_params - period = params[:parsed_frame].css('period').text - - # registrant = parse_registrant(params) - # domain_contacts = parse_domain_contacts_from_epp(params) - - registrant_code = params[:parsed_frame].css('registrant').text - owner_contact = Contact.find_by(code: registrant_code) - - unless owner_contact - epp_errors << { - code: '2303', - msg: I18n.t('registrant_not_found'), - value: { obj: 'registrant', val: registrant_code } - } - end - - { - name: params[:parsed_frame].css('name').text, - registrar_id: current_user.registrar.try(:id), - registered_at: Time.now, - period: (period.to_i == 0) ? 1 : period.to_i, - period_unit: Epp::EppDomain.parse_period_unit_from_frame(params[:parsed_frame]) || 'y', - owner_contact_id: owner_contact.try(:id), - nameservers_attributes: Epp::EppDomain.parse_nameservers_from_frame(params[:parsed_frame]), - domain_contacts_attributes: parse_domain_contacts_from_epp, - dnskeys_attributes: parse_dnskeys_from_frame(params[:parsed_frame].css('extension create')), - legal_documents_attributes: parse_legal_document_from_frame(params[:parsed_frame]) - } - end - - def parse_domain_contacts_from_epp - res = [] - params[:parsed_frame].css('contact').each do |x| - c = Contact.find_by(code: x.text).try(:id) - - unless c - epp_errors << { - code: '2303', - msg: I18n.t('contact_not_found'), - value: { obj: 'contact', val: x.text } - } - next - end - - res << { - contact_id: Contact.find_by(code: x.text).try(:id), - contact_type: x['type'], - contact_code_cache: x.text - } - end - - res - end - - def parse_dnskeys_from_frame(parsed_frame) - res = [] - # res = { ds_data: [], key_data: [] } - - # res[:max_sig_life] = parsed_frame.css('maxSigLife').first.try(:text) - - res = parse_ds_data_from_frame(parsed_frame, res) - parse_key_data_from_frame(parsed_frame, res) - end - - def parse_key_data_from_frame(parsed_frame, res) - parsed_frame.xpath('keyData').each do |x| - res << { - flags: x.css('flags').first.try(:text), - protocol: x.css('protocol').first.try(:text), - alg: x.css('alg').first.try(:text), - public_key: x.css('pubKey').first.try(:text), - ds_alg: 3, - ds_digest_type: Setting.ds_algorithm - } - end - - res - end - - def parse_ds_data_from_frame(parsed_frame, res) - parsed_frame.css('dsData').each do |x| - data = { - ds_key_tag: x.css('keyTag').first.try(:text), - ds_alg: x.css('alg').first.try(:text), - ds_digest_type: x.css('digestType').first.try(:text), - ds_digest: x.css('digest').first.try(:text) - } - - kd = x.css('keyData').first - data.merge!({ - flags: kd.css('flags').first.try(:text), - protocol: kd.css('protocol').first.try(:text), - alg: kd.css('alg').first.try(:text), - public_key: kd.css('pubKey').first.try(:text) - }) if kd - - res << data - end - - res - end - - def parse_legal_document_from_frame(parsed_frame) - ld = parsed_frame.css('legalDocument').first - return [] unless ld - - [{ - body: ld.text, - document_type: ld['type'] - }] - end - def domain_transfer_params res = {} res[:pw] = params[:parsed_frame].css('pw').first.try(:text) @@ -318,30 +197,37 @@ class Epp::DomainsController < EppController res end - def find_domain(secure = { secure: true }) + def find_domain domain_name = params[:parsed_frame].css('name').text.strip.downcase - domain = Epp::EppDomain.find_by(name: domain_name) + @domain = Epp::EppDomain.find_by(name: domain_name) - unless domain + unless @domain epp_errors << { code: '2303', msg: I18n.t('errors.messages.epp_domain_not_found'), value: { obj: 'name', val: domain_name } } - return nil + fail CanCan::AccessDenied end - return domain if domain.auth_info == params[:parsed_frame].css('authInfo pw').text + @domain + end - if (domain.registrar != current_user.registrar) && secure[:secure] == true - epp_errors << { - code: '2302', - msg: I18n.t('errors.messages.domain_exists_but_belongs_to_other_registrar'), - value: { obj: 'name', val: params[:parsed_frame].css('name').text.strip.downcase } - } - return nil - end - - domain + def find_password + @password = params[:parsed_frame].css('authInfo pw').text end end + + +# return domain if domain.auth_info == params[:parsed_frame].css('authInfo pw').text + +# if (domain.registrar != current_user.registrar) && secure[:secure] == true +# epp_errors << { +# code: '2302', +# msg: I18n.t('errors.messages.domain_exists_but_belongs_to_other_registrar'), +# value: { obj: 'name', val: params[:parsed_frame].css('name').text.strip.downcase } +# } +# return nil +# end + +# domain diff --git a/app/models/ability.rb b/app/models/ability.rb index bb47bb2a8..6be658f9b 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -25,6 +25,9 @@ class Ability 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 } + + # Epp::Domain + can(:info, Epp::EppDomain) { |d, pw| d.registrar_id == @user.registrar_id || d.auth_info == pw } end def user diff --git a/app/models/epp/epp_domain.rb b/app/models/epp/epp_domain.rb index dde5542d2..8e6642ea6 100644 --- a/app/models/epp/epp_domain.rb +++ b/app/models/epp/epp_domain.rb @@ -124,9 +124,9 @@ class Epp::EppDomain < Domain end def nameservers_attrs(frame, action) - if action == 'rem' - ns_list = Epp::EppDomain.parse_nameservers_from_frame(frame) + ns_list = nameservers_from(frame) + if action == 'rem' to_destroy = [] ns_list.each do |ns_attrs| nameserver = nameservers.where(ns_attrs).try(:first) @@ -142,10 +142,25 @@ class Epp::EppDomain < Domain return to_destroy else - return Epp::EppDomain.parse_nameservers_from_frame(frame) + return ns_list end end + def nameservers_from(frame) + res = [] + frame.css('hostAttr').each do |x| + host_attr = { + hostname: x.css('hostName').first.try(:text), + ipv4: x.css('hostAddr[ip="v4"]').first.try(:text), + ipv6: x.css('hostAddr[ip="v6"]').first.try(:text) + } + + res << host_attr.delete_if { |_k, v| v.blank? } + end + + res + end + def domain_contacts_attrs(frame, action) contact_list = domain_contact_list_from(frame) @@ -335,59 +350,6 @@ class Epp::EppDomain < Domain errors.empty? && super(at) end - - - - - - - - - - def parse_and_attach_domain_dependencies(parsed_frame) - attach_owner_contact(self.class.parse_owner_contact_from_frame(parsed_frame)) - attach_contacts(self.class.parse_contacts_from_frame(parsed_frame)) - attach_nameservers(self.class.parse_nameservers_from_frame(parsed_frame)) - attach_statuses(self.class.parse_statuses_from_frame(parsed_frame)) - attach_legal_document(self.class.parse_legal_document_from_frame(parsed_frame)) - errors.empty? - end - - def parse_and_detach_domain_dependencies(parsed_frame) - detach_contacts(self.class.parse_contacts_from_frame(parsed_frame)) - detach_nameservers(self.class.parse_nameservers_from_frame(parsed_frame)) - detach_statuses(self.class.parse_statuses_from_frame(parsed_frame)) - - errors.empty? - end - - def parse_and_attach_ds_data(parsed_frame) - attach_dnskeys(self.class.parse_dnskeys_from_frame(parsed_frame)) - - errors.empty? - end - - def parse_and_detach_ds_data(parsed_frame) - detach_dnskeys(self.class.parse_dnskeys_from_frame(parsed_frame)) - - errors.empty? - end - - def parse_and_update_domain_dependencies(parsed_frame) - owner_contact_code = parsed_frame.css('registrant').try(:text) - attach_owner_contact(owner_contact_code) if owner_contact_code.present? - - errors.empty? - end - - # TODO: Find out if there are any attributes that can be changed - # if not, delete this method - def parse_and_update_domain_attributes(_parsed_frame) - # assign_attributes(self.class.parse_update_params_from_frame(parsed_frame)) - - errors.empty? - end - def attach_legal_document(legal_document_data) return unless legal_document_data @@ -397,175 +359,6 @@ class Epp::EppDomain < Domain ) end - def attach_owner_contact(code) - return unless code - self.owner_contact = Contact.find_by(code: code) - - return if owner_contact - - add_epp_error('2303', 'registrant', code, [:owner_contact, :not_found]) - end - - def attach_contacts(contacts) - contacts.each do |k, v| - v.each do |x| - contact = Contact.find_by(code: x[:contact]) - unless contact - add_epp_error('2303', 'contact', x[:contact], [:domain_contacts, :not_found]) - next - end - - if k == :admin && contact.bic? - add_epp_error('2306', 'contact', x[:contact], [:domain_contacts, :admin_contact_can_be_only_citizen]) - next - end - - attach_contact(k, contact) - end - end - - attach_default_contacts if new_record? && owner_contact - end - - def attach_nameservers(ns_list) - ns_list.each do |ns_attrs| - nameservers.build(ns_attrs) - end - end - - def attach_statuses(status_list) - status_list.each do |x| - unless DomainStatus::CLIENT_STATUSES.include?(x[:value]) - add_epp_error('2303', 'status', x[:value], [:domain_statuses, :not_found]) - next - end - - domain_statuses.build( - value: x[:value], - description: x[:description] - ) - end - end - - def detach_contacts(contact_list) - to_destroy = [] - contact_list.each do |k, v| - v.each do |x| - contact = domain_contacts.joins(:contact).where(contacts: { code: x[:contact] }, contact_type: k.to_s) - if contact.blank? - add_epp_error('2303', 'contact', x[:contact], [:domain_contacts, :not_found]) - else - to_destroy << contact - end - end - end - - domain_contacts.destroy(to_destroy) - end - - def detach_nameservers(ns_list) - to_destroy = [] - ns_list.each do |ns_attrs| - nameserver = nameservers.where(ns_attrs) - if nameserver.blank? - add_epp_error('2303', 'hostAttr', ns_attrs[:hostname], [:nameservers, :not_found]) - else - to_destroy << nameserver - end - end - nameservers.destroy(to_destroy) - end - - def detach_statuses(status_list) - to_destroy = [] - status_list.each do |x| - unless DomainStatus::CLIENT_STATUSES.include?(x[:value]) - add_epp_error('2303', 'status', x[:value], [:domain_statuses, :not_found]) - next - end - - status = domain_statuses.find_by(value: x[:value]) - if status.blank? - add_epp_error('2303', 'status', x[:value], [:domain_statuses, :not_found]) - else - to_destroy << status - end - end - - domain_statuses.destroy(to_destroy) - end - - def attach_dnskeys(dnssec_data) - return false unless validate_dnssec_data(dnssec_data) - - dnssec_data[:ds_data].each do |ds_data| - dnskeys.build(ds_data) - end - - dnssec_data[:key_data].each do |x| - dnskeys.build({ - ds_alg: 3, - ds_digest_type: Setting.ds_algorithm - }.merge(x)) - end - end - - def validate_dnssec_data(dnssec_data) - ds_data_allowed?(dnssec_data) - # ds_data_with_keys_allowed?(dnssec_data) - key_data_allowed?(dnssec_data) - - errors.empty? - end - - def ds_data_allowed?(dnssec_data) - return if (dnssec_data[:ds_data].any? && Setting.ds_data_allowed) || dnssec_data[:ds_data].empty? - errors.add(:base, :ds_data_not_allowed) - end - - def ds_data_with_keys_allowed?(dnssec_data) - dnssec_data[:ds_data].each do |ds_data| - if key_data?(ds_data) && !Setting.ds_data_with_key_allowed - errors.add(:base, :ds_data_with_key_not_allowed) - return - end - end - end - - def key_data_allowed?(dnssec_data) - return if (dnssec_data[:key_data].any? && Setting.key_data_allowed) || dnssec_data[:key_data].empty? - errors.add(:base, :key_data_not_allowed) - end - - def key_data?(data) - key_data_attrs = [:public_key, :alg, :protocol, :flags] - (data.keys & key_data_attrs).any? - end - - def detach_dnskeys(dnssec_data) - return false unless validate_dnssec_data(dnssec_data) - to_destroy = [] - dnssec_data[:ds_data].each do |x| - ds = dnskeys.where(ds_key_tag: x[:ds_key_tag]) - if ds.blank? - add_epp_error('2303', 'keyTag', x[:key_tag], [:dnskeys, :not_found]) - else - to_destroy << ds - end - end - - dnssec_data[:key_data].each do |x| - ds = dnskeys.where(public_key: x[:public_key]) - if ds.blank? - add_epp_error('2303', 'publicKey', x[:public_key], [:dnskeys, :not_found]) - else - to_destroy << ds - end - end - - dnskeys.destroy(to_destroy) - end - ### RENEW ### def renew(cur_exp_date, period, unit = 'y') @@ -786,100 +579,12 @@ class Epp::EppDomain < Domain end class << self - def parse_contacts_from_frame(parsed_frame) - res = {} - DomainContact::TYPES.each do |ct| - res[ct.to_sym] ||= [] - parsed_frame.css("contact[type='#{ct}']").each do |x| - res[ct.to_sym] << Hash.from_xml(x.to_s).with_indifferent_access - end - end - - res - end - - def parse_nameservers_from_frame(parsed_frame) - res = [] - parsed_frame.css('hostAttr').each do |x| - host_attr = { - hostname: x.css('hostName').first.try(:text), - ipv4: x.css('hostAddr[ip="v4"]').first.try(:text), - ipv6: x.css('hostAddr[ip="v6"]').first.try(:text) - } - - res << host_attr.delete_if { |_k, v| v.blank? } - end - - res - end - - def parse_owner_contact_from_frame(parsed_frame) - parsed_frame.css('registrant').first.try(:text) - end - def parse_period_unit_from_frame(parsed_frame) p = parsed_frame.css('period').first return nil unless p p[:unit] end - def parse_statuses_from_frame(parsed_frame) - res = [] - - parsed_frame.css('status').each do |x| - res << { - value: x['s'], - description: x.text - } - end - res - end - - def parse_dnskeys_from_frame(parsed_frame) - res = { ds_data: [], key_data: [] } - - res[:max_sig_life] = parsed_frame.css('maxSigLife').first.try(:text) - - res = parse_ds_data_from_frame(parsed_frame, res) - parse_key_data_from_frame(parsed_frame, res) - end - - def parse_key_data_from_frame(parsed_frame, res) - parsed_frame.xpath('keyData').each do |x| - res[:key_data] << { - flags: x.css('flags').first.try(:text), - protocol: x.css('protocol').first.try(:text), - alg: x.css('alg').first.try(:text), - public_key: x.css('pubKey').first.try(:text) - } - end - - res - end - - def parse_ds_data_from_frame(parsed_frame, res) - parsed_frame.css('dsData').each do |x| - data = { - ds_key_tag: x.css('keyTag').first.try(:text), - ds_alg: x.css('alg').first.try(:text), - ds_digest_type: x.css('digestType').first.try(:text), - ds_digest: x.css('digest').first.try(:text) - } - - kd = x.css('keyData').first - data.merge!({ - flags: kd.css('flags').first.try(:text), - protocol: kd.css('protocol').first.try(:text), - alg: kd.css('alg').first.try(:text), - public_key: kd.css('pubKey').first.try(:text) - }) if kd - - res[:ds_data] << data - end - - res - end - def parse_legal_document_from_frame(parsed_frame) ld = parsed_frame.css('legalDocument').first return nil unless ld diff --git a/spec/epp/domain_spec.rb b/spec/epp/domain_spec.rb index 254078728..53ceed9e2 100644 --- a/spec/epp/domain_spec.rb +++ b/spec/epp/domain_spec.rb @@ -1490,8 +1490,8 @@ describe 'EPP Domain', epp: true do it 'can not see other registrar domains' do login_as :registrar2 do response = epp_plain_request(domain_info_xml(name: { value: domain.name }), :xml) - response[:result_code].should == '2302' - response[:msg].should == 'Domain exists but belongs to other registrar' + response[:result_code].should == '2201' + response[:msg].should == 'Authorization error' end end diff --git a/spec/models/epp_domain_spec.rb b/spec/models/epp_domain_spec.rb index 6139a7e90..b5c67509f 100644 --- a/spec/models/epp_domain_spec.rb +++ b/spec/models/epp_domain_spec.rb @@ -7,88 +7,5 @@ describe Epp::EppDomain do before(:each) do create_settings end - - it 'attaches valid statuses' do - domain.attach_statuses([ - { - value: DomainStatus::CLIENT_HOLD, - description: 'payment overdue' - }, - { - value: DomainStatus::CLIENT_DELETE_PROHIBITED - } - ]) - - domain.save - domain.reload - - expect(domain.domain_statuses.first.value).to eq(DomainStatus::CLIENT_HOLD) - expect(domain.domain_statuses.first.description).to eq('payment overdue') - - expect(domain.domain_statuses.last.value).to eq(DomainStatus::CLIENT_DELETE_PROHIBITED) - end - - it 'adds an epp error when invalid statuses are attached' do - domain.attach_statuses([ - { - value: DomainStatus::SERVER_HOLD, - description: 'payment overdue' - }, - { - value: DomainStatus::CLIENT_DELETE_PROHIBITED - } - ]) - - expect(domain.errors[:epp_errors].length).to eq(1) - - err = domain.errors[:epp_errors].first - - expect(err[:msg]).to eq('Status was not found') - expect(err[:value][:val]).to eq(DomainStatus::SERVER_HOLD) - end - - it 'detaches valid statuses' do - domain.attach_statuses([ - { - value: DomainStatus::CLIENT_HOLD, - description: 'payment overdue' - }, - { - value: DomainStatus::CLIENT_DELETE_PROHIBITED - } - ]) - - domain.save - - domain.detach_statuses([ - { - value: DomainStatus::CLIENT_HOLD - } - ]) - - domain.save - domain.reload - - expect(domain.domain_statuses.count).to eq(1) - - expect(domain.domain_statuses.first.value).to eq(DomainStatus::CLIENT_DELETE_PROHIBITED) - end - - it 'adds an epp error when invalid statuses are detached' do - domain.domain_statuses.create(value: DomainStatus::SERVER_HOLD) - - domain.detach_statuses([ - { - value: DomainStatus::SERVER_HOLD - } - ]) - - expect(domain.errors[:epp_errors].length).to eq(1) - - err = domain.errors[:epp_errors].first - - expect(err[:msg]).to eq('Status was not found') - expect(err[:value][:val]).to eq(DomainStatus::SERVER_HOLD) - end end end