diff --git a/.rubocop.yml b/.rubocop.yml index 07428af3b..472214c29 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,9 @@ AllCops: RunRailsCops: true + Exclude: + - 'db/schema.rb' + Metrics/LineLength: Max: 120 diff --git a/README.md b/README.md index d0cb43cf2..f0ff44346 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ Usual Rails 4 app installation, rvm and bundler are your friends. rvm install ruby-2.1.2 bundle rake db:setup + mv config/secrets-example.yml config/secrets.yml # generate your own keys + ### Apache with patched mod_epp (Debian 7/Ubuntu 14.04 LTS) @@ -39,7 +41,8 @@ Enable ssl: sudo a2enmod proxy_http sudo mkdir /etc/apache2/ssl sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt - sudo nano /etc/apache2/sites-available/epp_ssl.conf + sudo a2enmod ssl + sudo nano /etc/apache2/sites-enabled/epp_ssl.conf For development configuration, add: ```apache @@ -120,7 +123,7 @@ Wait for the greeting message on the STD, then send EPP/TCP frame: Testing --- -* Before running tests for the first time: `rake db:seed` +* Before running tests for the first time: `RAILS_ENV=test rake db:seed` * Run tests: `rake` * Run EPP tests: `rake test:epp` * Run all but EPP tests: `rake test:other` diff --git a/app/controllers/concerns/epp/common.rb b/app/controllers/concerns/epp/common.rb index d7f25c0e1..7b4b9abf5 100644 --- a/app/controllers/concerns/epp/common.rb +++ b/app/controllers/concerns/epp/common.rb @@ -60,6 +60,15 @@ module Epp::Common epp_errors.empty? end + def xml_nested_attrs_present?(array_ph, attributes ) + [array_ph].flatten.each do |ph| + attributes.each do |x| + epp_errors << {code: '2003', msg: I18n.t('errors.messages.required_parameter_missing', key: x.last)} unless has_attribute(ph, x) + end + end + epp_errors.empty? + end + def has_attribute(ph, path) path.reduce(ph) do |location, key| location.respond_to?(:keys) ? location[key] : nil diff --git a/app/helpers/epp/contacts_helper.rb b/app/helpers/epp/contacts_helper.rb index 465c2ccbc..497188887 100644 --- a/app/helpers/epp/contacts_helper.rb +++ b/app/helpers/epp/contacts_helper.rb @@ -1,124 +1,140 @@ -module Epp::ContactsHelper - def create_contact - @contact = Contact.new(contact_and_address_attributes) - render '/epp/contacts/create' and return if stamp(@contact) && @contact.save +module Epp + module ContactsHelper + def create_contact + @contact = Contact.new(contact_and_address_attributes) + render '/epp/contacts/create' and return if stamp(@contact) && @contact.save - handle_errors(@contact) - end - - def update_contact - code = params_hash['epp']['command']['update']['update'][:id] - @contact = Contact.where(code: code).first - if has_rights? && stamp(@contact) && @contact.update_attributes(contact_and_address_attributes(:update)) - render 'epp/contacts/update' - else - epp_errors << { code: '2303', msg: t('errors.messages.epp_obj_does_not_exist'), value: { obj: 'id', val: code } } if @contact == [] handle_errors(@contact) end - end - def delete_contact - Contact.transaction do + def update_contact + code = params_hash['epp']['command']['update']['update'][:id] + @contact = Contact.where(code: code).first + if rights? && stamp(@contact) && @contact.update_attributes(contact_and_address_attributes(:update)) + render 'epp/contacts/update' + else + contact_exists? + handle_errors(@contact) + end + end + + def delete_contact + Contact.transaction do + @contact = find_contact + handle_errors(@contact) and return unless @contact + handle_errors(@contact) and return unless @contact.destroy_and_clean + + render '/epp/contacts/delete' + end + end + + def check_contact + ph = params_hash['epp']['command']['check']['check'] + @contacts = Contact.check_availability(ph[:id]) + render '/epp/contacts/check' + end + + def info_contact + handle_errors and return unless rights? @contact = find_contact handle_errors(@contact) and return unless @contact - handle_errors(@contact) and return unless @contact.destroy_and_clean - - render '/epp/contacts/delete' + render 'epp/contacts/info' end - end - def check_contact - ph = params_hash['epp']['command']['check']['check'] - @contacts = Contact.check_availability(ph[:id]) - render '/epp/contacts/check' - end + ## HELPER METHODS - def info_contact - handle_errors and return unless has_rights? - @contact = find_contact - handle_errors(@contact) and return unless @contact - render 'epp/contacts/info' - end + private - ## HELPER METHODS + ## CREATE + def validate_contact_create_request + @ph = params_hash['epp']['command']['create']['create'] + xml_attrs_present?(@ph, [%w(id), + %w(authInfo pw), + %w(postalInfo)]) + return epp_errors.empty? unless @ph['postalInfo'].is_a?(Hash) || @ph['postalInfo'].is_a?(Array) - private - - ## CREATE - def validate_contact_create_request - @ph = params_hash['epp']['command']['create']['create'] - xml_attrs_present?(@ph, [['id'], - %w(authInfo pw), - %w(postalInfo name), - %w(postalInfo addr city), - %w(postalInfo addr cc)]) - end - - ## UPDATE - def validate_contact_update_request - @ph = params_hash['epp']['command']['update']['update'] - xml_attrs_present?(@ph, [['id']]) - end - - ## DELETE - def validate_contact_delete_request - @ph = params_hash['epp']['command']['delete']['delete'] - xml_attrs_present?(@ph, [['id']]) - end - - ## CHECK - def validate_contact_check_request - @ph = params_hash['epp']['command']['check']['check'] - xml_attrs_present?(@ph, [['id']]) - end - - ## INFO - def validate_contact_info_request - @ph = params_hash['epp']['command']['info']['info'] - xml_attrs_present?(@ph, [['id']]) - end - - ## SHARED - - def find_contact - contact = Contact.find_by(code: @ph[:id]) - unless contact - epp_errors << { code: '2303', msg: t('errors.messages.epp_obj_does_not_exist'), value: { obj: 'id', val: @ph[:id] } } + xml_nested_attrs_present?(@ph['postalInfo'], [%w(name), + %w(addr city), + %w(addr cc)]) end - contact - end - def has_rights? - pw = @ph.try(:[], :authInfo).try(:[], :pw) || @ph.try(:[], :chg).try(:[], :authInfo).try(:[], :pw) || [] - id = @ph[:id] - - return true if !find_contact.nil? && find_contact.auth_info_matches(pw) - - epp_errors << { code: '2201', msg: t('errors.messages.epp_authorization_error'), value: { obj: 'pw', val: pw } } - false - end - - def contact_and_address_attributes(type = :create) - case type - when :update - contact_hash = Contact.extract_attributes(@ph[:chg], type) - contact_hash[:address_attributes] = - Address.extract_attributes(( @ph.try(:[], :chg).try(:[], :postalInfo).try(:[], :addr) || []), type) - else - contact_hash = Contact.extract_attributes(@ph, type) - contact_hash[:address_attributes] = - Address.extract_attributes(( @ph.try(:[], :postalInfo).try(:[], :addr) || []), type) + ## UPDATE + def validate_contact_update_request + @ph = params_hash['epp']['command']['update']['update'] + xml_attrs_present?(@ph, [['id']]) end - contact_hash[:ident_type] = ident_type unless ident_type.nil? - contact_hash - end - def ident_type - result = params[:frame].slice(/(?<=\ 'urn:ietf:params:xml:ns:contact-1.0') do - xml.tag!('contact:name', @contact.name) - xml.tag!('contact:org', @contact.org_name) - xml.tag!('contact:addr') do - address = @contact.address - xml.tag!('contact:street', address.street) if address.street - xml.tag!('contact:street', address.street2) if address.street2 - xml.tag!('contact:street', address.street3) if address.street3 - xml.tag!('contact:cc', address.try(:country).try(:iso)) unless address.try(:country).nil? - end + xml << render('/epp/contacts/postal_info') xml.tag!('contact:voice', @contact.phone) xml.tag!('contact:fax', @contact.fax) xml.tag!('contact:email', @contact.email) diff --git a/config/secrets-example.yml b/config/secrets-example.yml new file mode 100644 index 000000000..23fedbe66 --- /dev/null +++ b/config/secrets-example.yml @@ -0,0 +1,8 @@ +development: + secret_key_base: generate-your-secret-key-by-rake-secret + +test: + secret_key_base: generate-your-secret-key-by-rake-secret + +production: + secret_key_base: diff --git a/db/migrate/20140822122938_add_postal_info_to_address.rb b/db/migrate/20140822122938_add_postal_info_to_address.rb new file mode 100644 index 000000000..427eab48a --- /dev/null +++ b/db/migrate/20140822122938_add_postal_info_to_address.rb @@ -0,0 +1,10 @@ +class AddPostalInfoToAddress < ActiveRecord::Migration + def change + add_column :addresses, :name, :string + add_column :addresses, :org_name, :string + add_column :addresses, :type, :string + + remove_column :contacts, :name, :string + remove_column :contacts, :org_name, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index f8fed151f..f72c9b6c0 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -26,11 +26,13 @@ ActiveRecord::Schema.define(version: 20140826103454) do t.datetime "updated_at" t.string "street2" t.string "street3" + t.string "name" + t.string "org_name" + t.string "type" end create_table "contacts", force: true do |t| t.string "code" - t.string "name" t.string "type" t.string "reg_no" t.string "phone" @@ -40,7 +42,6 @@ ActiveRecord::Schema.define(version: 20140826103454) do t.datetime "updated_at" t.string "ident" t.string "ident_type" - t.string "org_name" t.integer "created_by_id" t.integer "updated_by_id" t.string "auth_info" diff --git a/doc/epp_request_examples.xml b/doc/epp_request_examples.xml index 4692d56b2..5321241d0 100644 --- a/doc/epp_request_examples.xml +++ b/doc/epp_request_examples.xml @@ -135,3 +135,18 @@ ABC-12345 + + + + + + + + check-1234 + check-4321 + + + ABC-12345 + + diff --git a/lib/tasks/test.rake b/lib/tasks/test.rake index fadaf2db4..cc4a71430 100644 --- a/lib/tasks/test.rake +++ b/lib/tasks/test.rake @@ -16,6 +16,11 @@ RSpec::Core::RakeTask.new('test:other') do |t| t.rspec_opts = '--tag ~epp' end +desc 'Run all but EPP specs' +RSpec::Core::RakeTask.new('test:all_but_features') do |t| + t.rspec_opts = '--tag ~feature' +end + Rake::Task[:default].prerequisites.clear task default: :test diff --git a/spec/epp/contact_spec.rb b/spec/epp/contact_spec.rb index 536e0e9a7..64fef905a 100644 --- a/spec/epp/contact_spec.rb +++ b/spec/epp/contact_spec.rb @@ -29,17 +29,30 @@ describe 'EPP Contact', epp: true do expect(response[:result_code]).to eq('1000') expect(response[:msg]).to eq('Command completed successfully') expect(response[:clTRID]).to eq('ABC-12345') - expect(Contact.first.created_by_id).to be 1 - expect(Contact.first.updated_by_id).to be nil + expect(Contact.first.created_by_id).to eq 1 + expect(Contact.first.updated_by_id).to eq nil expect(Contact.count).to eq(1) - expect(Contact.first.org_name).to eq('Example Inc.') + + + expect(Contact.first.international_address.org_name).to eq('Example Inc.') expect(Contact.first.ident).to eq '37605030299' expect(Contact.first.ident_type).to eq 'op' - expect(Contact.first.address.street).to eq('123 Example Dr.') - expect(Contact.first.address.street2).to eq('Suite 100') - expect(Contact.first.address.street3).to eq nil + expect(Contact.first.international_address.street).to eq('123 Example Dr.') + expect(Contact.first.international_address.street2).to eq('Suite 100') + expect(Contact.first.international_address.street3).to eq nil + end + + it 'successfully creates contact with 2 addresses' do + response = epp_request('contacts/create_with_two_addresses.xml') + + expect(response[:result_code]).to eq('1000') + + expect(Contact.count).to eq(1) + expect(Contact.first.address).to_not eq Contact.first.local_address + expect(Address.count).to eq(2) + expect(LocalAddress.count).to eq(1) end it 'returns result data upon success' do @@ -62,6 +75,7 @@ describe 'EPP Contact', epp: true do response = epp_request(contact_create_xml, :xml) + expect(response[:result_code]).to eq('2302') expect(response[:msg]).to eq('Contact id already exists') @@ -204,8 +218,8 @@ describe 'EPP Contact', epp: true do end it 'returns info about contact' do - Fabricate(:contact, name: 'Johnny Awesome', created_by_id: '1', code: 'info-4444', auth_info: '2fooBAR') - Fabricate(:address) + Fabricate(:contact, created_by_id: '1', code: 'info-4444', auth_info: '2fooBAR', + international_address: Fabricate(:international_address, name: 'Johnny Awesome')) response = epp_request('contacts/info.xml') contact = response[:parsed].css('resData chkData') @@ -217,7 +231,7 @@ describe 'EPP Contact', epp: true do end it 'doesn\'t display unassociated object' do - Fabricate(:contact, name: 'Johnny Awesome', code: 'info-4444') + Fabricate(:contact, code: 'info-4444') response = epp_request('contacts/info.xml') expect(response[:result_code]).to eq('2201') diff --git a/spec/epp/requests/contacts/create_with_two_addresses.xml b/spec/epp/requests/contacts/create_with_two_addresses.xml new file mode 100644 index 000000000..f21d620d6 --- /dev/null +++ b/spec/epp/requests/contacts/create_with_two_addresses.xml @@ -0,0 +1,45 @@ + + + + + + loc_int + + John Doe Int + Example Int Inc. + + International street 1 + Dulles + VA + 20166-6503 + EE + + + + John Doe Loc + Example Loc Inc. + + Local street 1 + Vancouver + BC + 27123 + CA + + + +123.7035555555 + +1.7035555556 + jdoe@example.com + 37605030299 + + 2fooBAR + + + + + + + + ABC-12345 + + diff --git a/spec/fabricators/address_fabricator.rb b/spec/fabricators/address_fabricator.rb deleted file mode 100644 index 70aa7f867..000000000 --- a/spec/fabricators/address_fabricator.rb +++ /dev/null @@ -1,6 +0,0 @@ -Fabricator(:address) do - city Faker::Address.city - street Faker::Address.street_name - street2 Faker::Address.street_name - zip Faker::Address.zip -end diff --git a/spec/fabricators/contact_fabricator.rb b/spec/fabricators/contact_fabricator.rb index e6c6fec0e..bcba61a4d 100644 --- a/spec/fabricators/contact_fabricator.rb +++ b/spec/fabricators/contact_fabricator.rb @@ -1,10 +1,9 @@ Fabricator(:contact) do - name Faker::Name.name phone '+372.12345678' email Faker::Internet.email ident '37605030299' code { "sh#{Faker::Number.number(4)}" } ident_type 'op' auth_info 'ccds4324pok' - address + international_address end diff --git a/spec/fabricators/international_address_fabricator.rb b/spec/fabricators/international_address_fabricator.rb new file mode 100644 index 000000000..4b249f641 --- /dev/null +++ b/spec/fabricators/international_address_fabricator.rb @@ -0,0 +1,7 @@ +Fabricator(:international_address) do + name Faker::Name.name + city Faker::Address.city + street Faker::Address.street_name + street2 Faker::Address.street_name + zip Faker::Address.zip +end diff --git a/spec/features/setting_management_spec.rb b/spec/features/setting_management_spec.rb index fc962e088..6b4fdd4bc 100644 --- a/spec/features/setting_management_spec.rb +++ b/spec/features/setting_management_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -feature 'Setting management' do +feature 'Setting management', type: :feature do background { Fabricate(:domain_validation_setting_group) } scenario 'User changes a setting', js: true do diff --git a/spec/models/address_spec.rb b/spec/models/address_spec.rb index 96fa20adb..95a685016 100644 --- a/spec/models/address_spec.rb +++ b/spec/models/address_spec.rb @@ -7,13 +7,16 @@ end describe Address, '.extract_params' do it 'returns params hash'do - Fabricate(:country, iso: 'EE') - ph = { postalInfo: { name: 'fred', addr: { cc: 'EE', city: 'Village', street: %w(street1 street2) } } } - expect(Address.extract_attributes(ph[:postalInfo][:addr])).to eq({ - city: 'Village', - country_id: 1, - street: 'street1', - street2: 'street2' + Fabricate(:country, iso:'EE') + ph = { postalInfo: { name: "fred", addr: { cc: 'EE', city: 'Village', street: [ 'street1', 'street2' ] } } } + expect(Address.extract_attributes(ph[:postalInfo])).to eq( { + international_address_attributes: { + name: 'fred', + city: 'Village', + country_id: 1, + street: 'street1', + street2: 'street2', + } }) end end diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb index 286d87391..9ddd865f9 100644 --- a/spec/models/contact_spec.rb +++ b/spec/models/contact_spec.rb @@ -1,7 +1,8 @@ require 'rails_helper' describe Contact do - it { should have_one(:address) } + it { should have_one(:local_address) } + it { should have_one(:international_address) } context 'with invalid attribute' do before(:each) { @contact = Fabricate(:contact) } @@ -22,7 +23,6 @@ describe Contact do expect(@contact.errors.messages).to match_array({ code: ['Required parameter missing - code'], - name: ['Required parameter missing - name'], phone: ['Required parameter missing - phone', 'Phone nr is invalid'], email: ['Required parameter missing - email', 'Email is invalid'], ident: ['Required parameter missing - ident'] @@ -88,9 +88,8 @@ describe Contact, '.extract_params' do ph = { id: '123123', email: 'jdoe@example.com', postalInfo: { name: 'fred', addr: { cc: 'EE' } } } expect(Contact.extract_attributes(ph)).to eq({ code: '123123', - email: 'jdoe@example.com', - name: 'fred' - }) + email: 'jdoe@example.com' + } ) end end