diff --git a/app/helpers/epp/domains_helper.rb b/app/helpers/epp/domains_helper.rb index 95845c61c..167fddad7 100644 --- a/app/helpers/epp/domains_helper.rb +++ b/app/helpers/epp/domains_helper.rb @@ -63,10 +63,7 @@ module Epp::DomainsHelper @domain = find_domain handle_errors(@domain) and return unless @domain - - @domain.transfer_requested_at = Time.now - @domain.transferred_at = Time.now - @domain.save + handle_errors(@domain) and return unless @domain.transfer(@ph[:authInfo][:pw], current_epp_user) render '/epp/domains/transfer' end diff --git a/app/models/domain.rb b/app/models/domain.rb index fc40188ed..92429e403 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -30,6 +30,8 @@ class Domain < ActiveRecord::Base joins(:setting).where(settings: { setting_group_id: SettingGroup.domain_statuses.id }) } + has_many :domain_transfers + delegate :code, to: :owner_contact, prefix: true delegate :name, to: :registrar, prefix: true @@ -202,6 +204,38 @@ class Domain < ActiveRecord::Base save end + ### TRANSFER ### + def transfer(pw, current_user) + return false unless authenticate(pw) + return true if pending_transfer + + wait_time = SettingGroup.domain_general.setting(:transfer_wait_time).value.to_i + + if wait_time > 0 + domain_transfers.create( + status: DomainTransfer::PENDING, + transfer_requested_at: Time.zone.now, + transfer_to: current_user.registrar, + transfer_from: registrar + ) + else + domain_transfers.create( + status: DomainTransfer::SERVER_APPROVED, + transfer_requested_at: Time.zone.now, + transferred_at: Time.zone.now, + transfer_to: current_user.registrar, + transfer_from: registrar + ) + + self.registrar = current_user.registrar + save + end + end + + def pending_transfer + domain_transfers.find_by(status: DomainTransfer::PENDING) + end + ### VALIDATIONS ### def validate_nameservers_count diff --git a/app/models/domain_transfer.rb b/app/models/domain_transfer.rb new file mode 100644 index 000000000..79456b400 --- /dev/null +++ b/app/models/domain_transfer.rb @@ -0,0 +1,13 @@ +class DomainTransfer < ActiveRecord::Base + belongs_to :domain + + belongs_to :transfer_from, class_name: 'Registrar' + belongs_to :transfer_to, class_name: 'Registrar' + + PENDING = 'pending' + CLIENT_APPROVED = 'clientApproved' + CLIENT_CANCELLED = 'clientCancelled' + CLIENT_REJECTED = 'clientRejected' + SERVER_APPROVED = 'serverApproved' + SERVER_CANCELLED = 'serverCancelled' +end diff --git a/app/models/setting_group.rb b/app/models/setting_group.rb index 3fea54616..685520c6d 100644 --- a/app/models/setting_group.rb +++ b/app/models/setting_group.rb @@ -17,5 +17,9 @@ class SettingGroup < ActiveRecord::Base def domain_statuses find_by(code: 'domain_statuses') end + + def domain_general + find_by(code: 'domain_general') + end end end diff --git a/app/views/epp/domains/transfer.xml.builder b/app/views/epp/domains/transfer.xml.builder index 60e5c745f..dc732f480 100644 --- a/app/views/epp/domains/transfer.xml.builder +++ b/app/views/epp/domains/transfer.xml.builder @@ -7,11 +7,12 @@ xml.epp_head do xml.resData do xml.tag!('domain:trnData', 'xmlns:domain' => 'urn:ietf:params:xml:ns:domain-1.0') do xml.tag!('domain:name', @domain.name) - xml.tag!('domain:trStatus', 'serverApproved') - xml.tag!('domain:reID', current_epp_user.username) - xml.tag!('domain:reDate', @domain.transfer_requested_at) - xml.tag!('domain:acID', current_epp_user.username) - xml.tag!('domain:acDate', @domain.transferred_at) + ldt = @domain.domain_transfers.last + xml.tag!('domain:trStatus', ldt.status) + xml.tag!('domain:reID', ldt.transfer_to.reg_no) + xml.tag!('domain:reDate', ldt.transfer_requested_at) + xml.tag!('domain:acID', ldt.transfer_from.reg_no) + xml.tag!('domain:acDate', ldt.transferred_at) if ldt.transferred_at xml.tag!('domain:exDate', @domain.valid_to) end end diff --git a/db/migrate/20140828072329_populate_general_domain_settings.rb b/db/migrate/20140828072329_populate_general_domain_settings.rb new file mode 100644 index 000000000..a807a35dd --- /dev/null +++ b/db/migrate/20140828072329_populate_general_domain_settings.rb @@ -0,0 +1,10 @@ +class PopulateGeneralDomainSettings < ActiveRecord::Migration + def change + SettingGroup.create( + code: 'domain_general', + settings: [ + Setting.create(code: 'transfer_wait_time', value: 0) + ] + ) + end +end diff --git a/db/migrate/20140828074404_create_domain_transfer.rb b/db/migrate/20140828074404_create_domain_transfer.rb new file mode 100644 index 000000000..ad02f48fd --- /dev/null +++ b/db/migrate/20140828074404_create_domain_transfer.rb @@ -0,0 +1,14 @@ +class CreateDomainTransfer < ActiveRecord::Migration + def change + create_table :domain_transfers do |t| + t.integer :domain_id + t.string :status + t.datetime :transfer_requested_at + t.datetime :transferred_at + t.integer :transfer_from_id + t.integer :transfer_to_id + + t.timestamps + end + end +end diff --git a/db/migrate/20140828080320_remove_transfer_fields_from_domain.rb b/db/migrate/20140828080320_remove_transfer_fields_from_domain.rb new file mode 100644 index 000000000..a2fb3a087 --- /dev/null +++ b/db/migrate/20140828080320_remove_transfer_fields_from_domain.rb @@ -0,0 +1,7 @@ +class RemoveTransferFieldsFromDomain < ActiveRecord::Migration + def change + remove_column :domains, :transferred_at + remove_column :domains, :transfer_requested_at + remove_column :domains, :transfer_to + end +end diff --git a/db/schema.rb b/db/schema.rb index 8c08c938c..44356c295 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20140827140759) do +ActiveRecord::Schema.define(version: 20140828080320) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -73,6 +73,17 @@ ActiveRecord::Schema.define(version: 20140827140759) do t.string "description" end + create_table "domain_transfers", force: true do |t| + t.integer "domain_id" + t.string "status" + t.datetime "transfer_requested_at" + t.datetime "transferred_at" + t.integer "transfer_from_id" + t.integer "transfer_to_id" + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "domains", force: true do |t| t.string "name" t.integer "registrar_id" @@ -90,10 +101,7 @@ ActiveRecord::Schema.define(version: 20140827140759) do t.string "name_dirty" t.string "name_puny" t.integer "period" - t.string "period_unit", limit: 1 - t.datetime "transferred_at" - t.datetime "transfer_requested_at" - t.integer "transfer_to" + t.string "period_unit", limit: 1 end create_table "epp_sessions", force: true do |t| diff --git a/spec/epp/domain_spec.rb b/spec/epp/domain_spec.rb index bb97dee67..a27db7384 100644 --- a/spec/epp/domain_spec.rb +++ b/spec/epp/domain_spec.rb @@ -29,6 +29,61 @@ describe 'EPP Domain', epp: true do expect(response[:clTRID]).to eq('ABC-12345') end + context 'with two epp users' do + before(:each) do + elkdata = Fabricate(:registrar, + name: 'Elkdata', + reg_no: '123' + ) + + Fabricate(:epp_user, username: 'elkdata_user', registrar: elkdata) + Fabricate(:domain_general_setting_group) + Fabricate(:domain, name: 'example.ee', registrar: elkdata) + end + + it 'transfers a domain' do + response = epp_request('domains/transfer.xml') + + d = Domain.first + dtl = d.domain_transfers.last + + trn_data = response[:parsed].css('trnData') + expect(trn_data.css('name').text).to eq('example.ee') + expect(trn_data.css('trStatus').text).to eq('serverApproved') + expect(trn_data.css('reID').text).to eq('10577829') + expect(trn_data.css('reDate').text).to eq(dtl.transfer_requested_at.to_time.utc.to_s) + expect(trn_data.css('acID').text).to eq('123') + expect(trn_data.css('acDate').text).to eq(dtl.transferred_at.to_time.utc.to_s) + expect(trn_data.css('exDate').text).to eq(d.valid_to.to_time.utc.to_s) + + s = Setting.find_by(code: 'transfer_wait_time') + s.update(value: 1) + + response = epp_request('domains/transfer.xml') + trn_data = response[:parsed].css('trnData') + d = Domain.first + + expect(trn_data.css('name').text).to eq('example.ee') + expect(trn_data.css('trStatus').text).to eq('pending') + expect(trn_data.css('reID').text).to eq('10577829') + expect(trn_data.css('reDate').text).to eq(dtl.transfer_requested_at.to_time.utc.to_s) + expect(trn_data.css('acID').text).to eq('10577829') + expect(trn_data.css('exDate').text).to eq(d.valid_to.to_time.utc.to_s) + + # should return same data if pending already + response = epp_request('domains/transfer.xml') + trn_data = response[:parsed].css('trnData') + d = Domain.first + + expect(trn_data.css('name').text).to eq('example.ee') + expect(trn_data.css('trStatus').text).to eq('pending') + expect(trn_data.css('reID').text).to eq('10577829') + expect(trn_data.css('reDate').text).to eq(dtl.transfer_requested_at.to_time.utc.to_s) + expect(trn_data.css('acID').text).to eq('10577829') + expect(trn_data.css('exDate').text).to eq(d.valid_to.to_time.utc.to_s) + end + end + context 'with citizen as an owner' do before(:each) do Fabricate(:contact, code: 'jd1234') @@ -349,10 +404,6 @@ describe 'EPP Domain', epp: true do expect(d.owner_contact_code).to eq('mak21') expect(d.auth_info).to eq('2BARfoo') end - - it 'transfers a domain' do - response = epp_request('domains/transfer.xml') - end end it 'checks a domain' do diff --git a/spec/fabricators/setting_group_fabricator.rb b/spec/fabricators/setting_group_fabricator.rb index dc31c534c..ae63fc206 100644 --- a/spec/fabricators/setting_group_fabricator.rb +++ b/spec/fabricators/setting_group_fabricator.rb @@ -27,3 +27,12 @@ Fabricator(:domain_statuses_setting_group, from: :setting_group) do ] end end + +Fabricator(:domain_general_setting_group, from: :setting_group) do + code 'domain_general' + settings do + [ + Fabricate(:setting, code: 'transfer_wait_time', value: '0') + ] + end +end diff --git a/spec/models/domain_spec.rb b/spec/models/domain_spec.rb index 529e5ebe3..7259d615b 100644 --- a/spec/models/domain_spec.rb +++ b/spec/models/domain_spec.rb @@ -6,6 +6,7 @@ describe Domain do it { should belong_to(:owner_contact) } it { should have_many(:tech_contacts) } it { should have_many(:admin_contacts) } + it { should have_many(:domain_transfers) } context 'with sufficient settings' do before(:each) { Fabricate(:domain_validation_setting_group) } diff --git a/spec/models/domain_transfer_spec.rb b/spec/models/domain_transfer_spec.rb new file mode 100644 index 000000000..17c12dfe4 --- /dev/null +++ b/spec/models/domain_transfer_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +describe DomainTransfer do + it { should belong_to(:domain) } +end