diff --git a/.rubocop.yml b/.rubocop.yml
index cc32da4b9..3d8fd0b90 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -1 +1,4 @@
inherit_from: .rubocop_todo.yml
+
+Style/Alias:
+ EnforcedStyle: prefer_alias_method
diff --git a/app/api/repp/domain_transfers_v1.rb b/app/api/repp/domain_transfers_v1.rb
index eca21b62d..c6a48df6d 100644
--- a/app/api/repp/domain_transfers_v1.rb
+++ b/app/api/repp/domain_transfers_v1.rb
@@ -25,7 +25,7 @@ module Repp
if domain
if domain.transfer_code == transfer_code
- domain.transfer(new_registrar)
+ DomainTransfer.request(domain, new_registrar)
successful_domain_transfers << { type: 'domain_transfer', attributes: { domain_name: domain.name } }
else
errors << { title: "#{domain_name} transfer code is wrong" }
diff --git a/app/controllers/epp/domains_controller.rb b/app/controllers/epp/domains_controller.rb
index 02c75c7da..3b8b94155 100644
--- a/app/controllers/epp/domains_controller.rb
+++ b/app/controllers/epp/domains_controller.rb
@@ -142,6 +142,13 @@ class Epp::DomainsController < EppController
authorize! :transfer, @domain, @password
action = params[:parsed_frame].css('transfer').first[:op]
+ if @domain.non_transferable?
+ throw :epp_error, {
+ code: '2304',
+ msg: I18n.t(:object_status_prohibits_operation)
+ }
+ end
+
@domain_transfer = @domain.transfer(params[:parsed_frame], action, current_user)
if @domain_transfer
diff --git a/app/controllers/epp/polls_controller.rb b/app/controllers/epp/polls_controller.rb
index fb032975f..44f8afdc1 100644
--- a/app/controllers/epp/polls_controller.rb
+++ b/app/controllers/epp/polls_controller.rb
@@ -6,6 +6,8 @@ class Epp::PollsController < EppController
ack_poll if params[:parsed_frame].css('poll').first['op'] == 'ack'
end
+ private
+
def req_poll
@message = current_user.queued_messages.last
@@ -49,8 +51,6 @@ class Epp::PollsController < EppController
render_epp_response 'epp/poll/poll_ack'
end
- private
-
def validate_poll
requires_attribute 'poll', 'op', values: %(ack req), allow_blank: true
end
diff --git a/app/controllers/epp_controller.rb b/app/controllers/epp_controller.rb
index eee6cef7a..36bdcd6cc 100644
--- a/app/controllers/epp_controller.rb
+++ b/app/controllers/epp_controller.rb
@@ -335,7 +335,6 @@ class EppController < ApplicationController
# rubocop: disable Metrics/CyclomaticComplexity
# rubocop: disable Metrics/PerceivedComplexity
def write_to_epp_log
- # return nil if EPP_LOG_ENABLED
request_command = params[:command] || params[:action] # error receives :command, other methods receive :action
frame = params[:raw_frame] || params[:frame]
diff --git a/app/models/concerns/domain/transferable.rb b/app/models/concerns/domain/transferable.rb
index 62b70a71b..f2e7736c2 100644
--- a/app/models/concerns/domain/transferable.rb
+++ b/app/models/concerns/domain/transferable.rb
@@ -2,31 +2,18 @@ module Concerns::Domain::Transferable
extend ActiveSupport::Concern
included do
- after_initialize :generate_transfer_code, if: 'new_record? && transfer_code.blank?'
+ after_initialize :generate_transfer_code, if: :generate_transfer_code?
+ end
+
+ def non_transferable?
+ !transferable?
end
def transfer(new_registrar)
- old_registrar = registrar
-
self.registrar = new_registrar
regenerate_transfer_code
- contact_codes = contacts.pluck(:code).sort.uniq
- registrant_code = registrant.code
-
transaction do
- old_registrar.messages.create!(
- body: I18n.t('domain_transfer_was_approved', contacts: contact_codes, registrant: registrant_code),
- attached_obj_id: id,
- attached_obj_type: self.class.name
- )
-
- domain_transfers.create!(
- transfer_requested_at: Time.zone.now,
- old_registrar: old_registrar,
- new_registrar: new_registrar
- )
-
transfer_contacts(new_registrar)
save!
end
@@ -34,6 +21,24 @@ module Concerns::Domain::Transferable
private
+ def transferable?
+ (statuses & [
+ DomainStatus::PENDING_DELETE_CONFIRMATION,
+ DomainStatus::PENDING_CREATE,
+ DomainStatus::PENDING_UPDATE,
+ DomainStatus::PENDING_DELETE,
+ DomainStatus::PENDING_RENEW,
+ DomainStatus::PENDING_TRANSFER,
+ DomainStatus::FORCE_DELETE,
+ DomainStatus::SERVER_TRANSFER_PROHIBITED,
+ DomainStatus::CLIENT_TRANSFER_PROHIBITED
+ ]).empty?
+ end
+
+ def generate_transfer_code?
+ new_record? && transfer_code.blank?
+ end
+
def generate_transfer_code
self.transfer_code = SecureRandom.hex
end
diff --git a/app/models/domain.rb b/app/models/domain.rb
index 31ba838f2..54dfe608e 100644
--- a/app/models/domain.rb
+++ b/app/models/domain.rb
@@ -49,7 +49,7 @@ class Domain < ActiveRecord::Base
accepts_nested_attributes_for :domain_statuses, allow_destroy: true,
reject_if: proc { |attrs| attrs[:value].blank? }
- has_many :domain_transfers, dependent: :destroy
+ has_many :transfers, class_name: 'DomainTransfer', dependent: :destroy
has_many :dnskeys, dependent: :destroy
@@ -280,7 +280,7 @@ class Domain < ActiveRecord::Base
end
def pending_transfer
- domain_transfers.find_by(status: DomainTransfer::PENDING)
+ transfers.find_by(status: DomainTransfer::PENDING)
end
def server_holdable?
diff --git a/app/models/domain_transfer.rb b/app/models/domain_transfer.rb
index 6dd539bb8..6982f36b6 100644
--- a/app/models/domain_transfer.rb
+++ b/app/models/domain_transfer.rb
@@ -10,6 +10,26 @@ class DomainTransfer < ActiveRecord::Base
SERVER_APPROVED = 'serverApproved'
before_create :set_wait_until
+
+ class << self
+ def request(domain, new_registrar)
+ domain_transfer = create!(
+ transfer_requested_at: Time.zone.now,
+ domain: domain,
+ old_registrar: domain.registrar,
+ new_registrar: new_registrar
+ )
+
+ domain_transfer.approve if approve_automatically?
+ end
+
+ private
+
+ def approve_automatically?
+ Setting.transfer_wait_time.zero?
+ end
+ end
+
def set_wait_until
wait_time = Setting.transfer_wait_time
return if wait_time == 0
@@ -17,6 +37,7 @@ class DomainTransfer < ActiveRecord::Base
end
before_create :set_status
+
def set_status
if Setting.transfer_wait_time > 0
self.status = PENDING unless status
@@ -36,11 +57,29 @@ class DomainTransfer < ActiveRecord::Base
status == PENDING
end
- def notify_losing_registrar(contacts, registrant)
+ def approve
+ transaction do
+ self.status = SERVER_APPROVED
+ save!
+
+ notify_old_registrar
+ domain.transfer(new_registrar)
+ end
+ end
+
+ private
+
+ def notify_old_registrar
+ old_contacts_codes = domain.contacts.pluck(:code).sort.uniq.join(', ')
+ old_registrant_code = domain.registrant.code
+
old_registrar.messages.create!(
- body: I18n.t('domain_transfer_was_approved', contacts: contacts, registrant: registrant),
+ body: I18n.t('messages.texts.domain_transfer',
+ domain_name: domain.name,
+ old_contacts_codes: old_contacts_codes,
+ old_registrant_code: old_registrant_code),
attached_obj_id: id,
- attached_obj_type: self.class.to_s
+ attached_obj_type: self.class.name
)
end
end
diff --git a/app/models/epp/domain.rb b/app/models/epp/domain.rb
index a59094d1e..8c9e8bcc8 100644
--- a/app/models/epp/domain.rb
+++ b/app/models/epp/domain.rb
@@ -628,7 +628,7 @@ class Epp::Domain < Domain
case action
when 'query'
- return domain_transfers.last if domain_transfers.any?
+ return transfers.last if transfers.any?
when 'request'
return pending_transfer if pending_transfer
return query_transfer(frame, current_user)
@@ -644,13 +644,6 @@ class Epp::Domain < Domain
# rubocop: disable Metrics/MethodLength
# rubocop: disable Metrics/AbcSize
def query_transfer(frame, current_user)
- unless transferrable?
- throw :epp_error, {
- code: '2304',
- msg: I18n.t(:object_status_prohibits_operation)
- }
- end
-
if current_user.registrar == registrar
throw :epp_error, {
code: '2002',
@@ -658,11 +651,8 @@ class Epp::Domain < Domain
}
end
- old_contact_codes = contacts.pluck(:code).sort.uniq
- old_registrant_code = registrant.code
-
transaction do
- dt = domain_transfers.create!(
+ dt = transfers.create!(
transfer_requested_at: Time.zone.now,
old_registrar: registrar,
new_registrar: current_user.registrar
@@ -677,8 +667,8 @@ class Epp::Domain < Domain
end
if dt.approved?
+ dt.send(:notify_old_registrar)
transfer_contacts(current_user.registrar)
- dt.notify_losing_registrar(old_contact_codes, old_registrant_code)
regenerate_transfer_code
self.registrar = current_user.registrar
end
@@ -811,20 +801,6 @@ class Epp::Domain < Domain
true
end
- def transferrable?
- (statuses & [
- DomainStatus::PENDING_DELETE_CONFIRMATION,
- DomainStatus::PENDING_CREATE,
- DomainStatus::PENDING_UPDATE,
- DomainStatus::PENDING_DELETE,
- DomainStatus::PENDING_RENEW,
- DomainStatus::PENDING_TRANSFER,
- DomainStatus::FORCE_DELETE,
- DomainStatus::SERVER_TRANSFER_PROHIBITED,
- DomainStatus::CLIENT_TRANSFER_PROHIBITED
- ]).empty?
- end
-
## SHARED
# For domain transfer
diff --git a/app/models/message.rb b/app/models/message.rb
index 10d823e63..1f01842c8 100644
--- a/app/models/message.rb
+++ b/app/models/message.rb
@@ -1,6 +1,6 @@
class Message < ActiveRecord::Base
include Versions # version/message_version.rb
- belongs_to :registrar
+ belongs_to :registrar, required: true
before_create -> { self.queued = true }
diff --git a/app/models/registrar.rb b/app/models/registrar.rb
index 7646b2ceb..46022808f 100644
--- a/app/models/registrar.rb
+++ b/app/models/registrar.rb
@@ -137,15 +137,6 @@ class Registrar < ActiveRecord::Base
cash_account.account_activities.create!(args)
end
- def domain_transfers
- at = DomainTransfer.arel_table
- DomainTransfer.where(
- at[:new_registrar_id].eq(id).or(
- at[:old_registrar_id].eq(id)
- )
- )
- end
-
def address
[street, city, state, zip].reject(&:blank?).compact.join(', ')
end
diff --git a/app/views/registrar/polls/show.haml b/app/views/registrar/polls/show.haml
index 69e74751b..c4c337749 100644
--- a/app/views/registrar/polls/show.haml
+++ b/app/views/registrar/polls/show.haml
@@ -2,7 +2,7 @@
- msg_q = @data.css('msgQ').first
.row
.col-sm-12
- %h2= t('messages', count: msg_q['count'])
+ %h2= t '.header', count: msg_q['count']
%hr
.row
.col-md-12
@@ -75,7 +75,7 @@
- else
.row
.col-sm-12
- %h2= t('messages', count: 0)
+ %h2= t '.header', count: 0
%hr
.row
.col-md-12
diff --git a/config/initializers/initial_settings.rb b/config/initializers/initial_settings.rb
index 94ff1dc7e..5ae521bc5 100644
--- a/config/initializers/initial_settings.rb
+++ b/config/initializers/initial_settings.rb
@@ -73,6 +73,3 @@ if con.present? && con.table_exists?('settings')
Setting.save_default(:registry_swift, 'LHVBEE22')
Setting.save_default(:registry_invoice_contact, 'Martti Õigus')
end
-
-# dev only setting
-EPP_LOG_ENABLED = true # !Rails.env.test?
diff --git a/config/locales/en.yml b/config/locales/en.yml
index da6df608a..c37cb9a48 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -214,20 +214,12 @@ en:
blank: 'is missing'
epp_domain_reserved: 'Domain name is reserved'
epp_obj_does_not_exist: 'Object does not exist'
- epp_command_failed: 'Command failed'
epp_authorization_error: 'Authorization error'
- epp_authentication_error: 'Authentication error'
epp_id_taken: 'Contact id already exists'
epp_domain_not_found: 'Domain not found'
epp_exp_dates_do_not_match: 'Given and current expire dates do not match'
- epp_registrant_not_found: 'Registrant not found'
- epp_command_syntax_error: 'Command syntax error'
required_parameter_missing: 'Required parameter missing: %{key}'
- attr_missing: 'Required parameter missing: %{key}'
- repeating_postal_info: 'Only one of each postal info types may be provided'
- invalid_type: 'PostalInfo type is invalid'
unimplemented_command: 'Unimplemented command'
- domain_exists_but_belongs_to_other_registrar: 'Domain exists but belongs to other registrar'
required_ident_attribute_missing: "Required ident attribute missing: %{key}"
invalid_iso31661_alpha2: does not conform to ISO 3166-1 alpha-2 standard
invalid_iso8601_date: has invalid date format YYYY-MM-DD (ISO 8601)
@@ -451,7 +443,6 @@ en:
client_side_status_editing_error: 'Parameter value policy error. Client-side object status management not supported'
switch_to: Switch to
admin_menu: Admin
- domain_transfer_was_approved: 'Domain transfer was approved, associated contacts were: %{contacts} and registrant was %{registrant}'
business_registry_service_not_available: "Business Registry service Ärireg is not available"
# DEPP
@@ -526,7 +517,6 @@ en:
address: 'Address'
street: 'Street'
city: 'City'
- messages: 'Messages (%{count})'
message: 'Message'
message_no: 'Message #%{id}'
queue_date: 'Queue date'
@@ -754,7 +744,6 @@ en:
parameter_value_range_error: 'Parameter value range error: %{key}'
payment_received: 'Payment received'
api_user_not_found: 'API user not found'
- domain_already_belongs_to_the_querying_registrar: 'Domain already belongs to the querying registrar'
notes: Notes
active_price_for_this_operation_is: 'Active price for this operation is %{price}'
active_price_missing_for_this_operation: 'Active price missing for this operation!'
diff --git a/config/locales/messages.en.yml b/config/locales/messages.en.yml
new file mode 100644
index 000000000..0c85bb49c
--- /dev/null
+++ b/config/locales/messages.en.yml
@@ -0,0 +1,7 @@
+en:
+ messages:
+ texts:
+ domain_transfer: >-
+ Transfer of domain %{domain_name} has been approved.
+ It was associated with registrant %{old_registrant_code}
+ and contacts %{old_contacts_codes}.
diff --git a/config/locales/registrar/polls.en.yml b/config/locales/registrar/polls.en.yml
new file mode 100644
index 000000000..4d09e54f4
--- /dev/null
+++ b/config/locales/registrar/polls.en.yml
@@ -0,0 +1,5 @@
+en:
+ registrar:
+ polls:
+ show:
+ header: Messages (%{count})
diff --git a/db/migrate/20180211011450_change_messages_registrar_id_to_not_null.rb b/db/migrate/20180211011450_change_messages_registrar_id_to_not_null.rb
new file mode 100644
index 000000000..962022ae0
--- /dev/null
+++ b/db/migrate/20180211011450_change_messages_registrar_id_to_not_null.rb
@@ -0,0 +1,5 @@
+class ChangeMessagesRegistrarIdToNotNull < ActiveRecord::Migration
+ def change
+ change_column_null :messages, :registrar_id, false
+ end
+end
diff --git a/db/migrate/20180211011948_add_messages_registrar_id_fk.rb b/db/migrate/20180211011948_add_messages_registrar_id_fk.rb
new file mode 100644
index 000000000..af8df7b97
--- /dev/null
+++ b/db/migrate/20180211011948_add_messages_registrar_id_fk.rb
@@ -0,0 +1,5 @@
+class AddMessagesRegistrarIdFk < ActiveRecord::Migration
+ def change
+ add_foreign_key :messages, :registrars, name: 'messages_registrar_id_fk'
+ end
+end
diff --git a/db/migrate/20180214200224_add_domain_transfers_constraints.rb b/db/migrate/20180214200224_add_domain_transfers_constraints.rb
new file mode 100644
index 000000000..bd4023deb
--- /dev/null
+++ b/db/migrate/20180214200224_add_domain_transfers_constraints.rb
@@ -0,0 +1,7 @@
+class AddDomainTransfersConstraints < ActiveRecord::Migration
+ def change
+ change_column_null :domain_transfers, :domain_id, false
+ change_column_null :domain_transfers, :old_registrar_id, false
+ change_column_null :domain_transfers, :new_registrar_id, false
+ end
+end
diff --git a/db/migrate/20180214213743_change_messages_body_to_not_null.rb b/db/migrate/20180214213743_change_messages_body_to_not_null.rb
new file mode 100644
index 000000000..4a09101f1
--- /dev/null
+++ b/db/migrate/20180214213743_change_messages_body_to_not_null.rb
@@ -0,0 +1,5 @@
+class ChangeMessagesBodyToNotNull < ActiveRecord::Migration
+ def change
+ change_column_null :messages, :body, false
+ end
+end
diff --git a/db/migrate/20180218004148_change_messages_attached_obj_id_type_to_int.rb b/db/migrate/20180218004148_change_messages_attached_obj_id_type_to_int.rb
new file mode 100644
index 000000000..9996b5e67
--- /dev/null
+++ b/db/migrate/20180218004148_change_messages_attached_obj_id_type_to_int.rb
@@ -0,0 +1,5 @@
+class ChangeMessagesAttachedObjIdTypeToInt < ActiveRecord::Migration
+ def change
+ change_column :messages, :attached_obj_id, 'integer USING attached_obj_id::integer'
+ end
+end
diff --git a/db/structure.sql b/db/structure.sql
index 449ec44f8..237c82e66 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -954,12 +954,12 @@ ALTER SEQUENCE domain_statuses_id_seq OWNED BY domain_statuses.id;
CREATE TABLE domain_transfers (
id integer NOT NULL,
- domain_id integer,
+ domain_id integer NOT NULL,
status character varying,
transfer_requested_at timestamp without time zone,
transferred_at timestamp without time zone,
- old_registrar_id integer,
- new_registrar_id integer,
+ old_registrar_id integer NOT NULL,
+ new_registrar_id integer NOT NULL,
created_at timestamp without time zone,
updated_at timestamp without time zone,
wait_until timestamp without time zone
@@ -2183,10 +2183,10 @@ ALTER SEQUENCE mail_templates_id_seq OWNED BY mail_templates.id;
CREATE TABLE messages (
id integer NOT NULL,
- registrar_id integer,
- body character varying,
+ registrar_id integer NOT NULL,
+ body character varying NOT NULL,
attached_obj_type character varying,
- attached_obj_id character varying,
+ attached_obj_id integer,
queued boolean,
created_at timestamp without time zone,
updated_at timestamp without time zone,
@@ -4524,6 +4524,14 @@ ALTER TABLE ONLY account_activities
ADD CONSTRAINT fk_rails_d2cc3c2fa9 FOREIGN KEY (price_id) REFERENCES prices(id);
+--
+-- Name: messages_registrar_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY messages
+ ADD CONSTRAINT messages_registrar_id_fk FOREIGN KEY (registrar_id) REFERENCES registrars(id);
+
+
--
-- Name: user_registrar_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@@ -5086,6 +5094,10 @@ INSERT INTO schema_migrations (version) VALUES ('20180207071528');
INSERT INTO schema_migrations (version) VALUES ('20180207072139');
+INSERT INTO schema_migrations (version) VALUES ('20180211011450');
+
+INSERT INTO schema_migrations (version) VALUES ('20180211011948');
+
INSERT INTO schema_migrations (version) VALUES ('20180212123810');
INSERT INTO schema_migrations (version) VALUES ('20180212152810');
@@ -5094,3 +5106,9 @@ INSERT INTO schema_migrations (version) VALUES ('20180212154731');
INSERT INTO schema_migrations (version) VALUES ('20180213183818');
+INSERT INTO schema_migrations (version) VALUES ('20180214200224');
+
+INSERT INTO schema_migrations (version) VALUES ('20180214213743');
+
+INSERT INTO schema_migrations (version) VALUES ('20180218004148');
+
diff --git a/doc/controllers_complete.svg b/doc/controllers_complete.svg
index 68d02cf4a..765d4a08b 100644
--- a/doc/controllers_complete.svg
+++ b/doc/controllers_complete.svg
@@ -86,9 +86,7 @@
Epp::PollsController
-ack_poll
poll
-req_poll
_layout
diff --git a/spec/factories/message.rb b/spec/factories/message.rb
deleted file mode 100644
index 6ae235aaf..000000000
--- a/spec/factories/message.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-FactoryBot.define do
- factory :message do
- body 'fabricator body'
- end
-end
diff --git a/spec/models/message_spec.rb b/spec/models/message_spec.rb
deleted file mode 100644
index a71988701..000000000
--- a/spec/models/message_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-require 'rails_helper'
-
-describe Message do
- context 'with invalid attribute' do
- before :all do
- @mssage = Message.new
- end
-
- it 'should not be valid' do
- @mssage.valid?
- @mssage.errors.full_messages.should match_array([
- "Body is missing"
- ])
- end
-
- it 'should not have any versions' do
- @mssage.versions.should == []
- end
- end
-
- context 'with valid attributes' do
- before :all do
- @mssage = create(:message)
- end
-
- it 'should be valid' do
- @mssage.valid?
- @mssage.errors.full_messages.should match_array([])
- end
-
- it 'should be valid twice' do
- @mssage = create(:message)
- @mssage.valid?
- @mssage.errors.full_messages.should match_array([])
- end
-
- it 'should have one version' do
- with_versioning do
- @mssage.versions.should == []
- @mssage.body = 'New body'
- @mssage.save
- @mssage.errors.full_messages.should match_array([])
- @mssage.versions.size.should == 1
- end
- end
- end
-end
diff --git a/spec/requests/epp/domain/transfer/discarded_spec.rb b/spec/requests/epp/domain/transfer/discarded_spec.rb
deleted file mode 100644
index 26596d993..000000000
--- a/spec/requests/epp/domain/transfer/discarded_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe 'EPP domain:transfer' do
- let(:registrar) { create(:registrar) }
- let(:user) { create(:api_user_epp, registrar: registrar) }
- let(:session_id) { create(:epp_session, user: user).session_id }
- let(:request_xml) { <<-XML
-
-
-
-
-
- test.com
-
- 98oiewslkfkd
-
-
-
-
-
- XML
- }
-
- before :example do
- login_as user
- end
-
- context 'when domain is not discarded' do
- let!(:domain) { create(:domain, name: 'test.com') }
-
- it 'returns epp code of 1000' do
- post '/epp/command/transfer', { frame: request_xml }, 'HTTP_COOKIE' => "session=#{session_id}"
- expect(response).to have_code_of(1000)
- end
- end
-
- context 'when domain is discarded' do
- let!(:domain) { create(:domain_discarded, name: 'test.com') }
-
- it 'returns epp code of 2105' do
- post '/epp/command/transfer', { frame: request_xml }, 'HTTP_COOKIE' => "session=#{session_id}"
- expect(response).to have_code_of(2105)
- end
- end
-end
diff --git a/test/fixtures/contacts.yml b/test/fixtures/contacts.yml
index 8c0fb4e10..eaf4401b7 100644
--- a/test/fixtures/contacts.yml
+++ b/test/fixtures/contacts.yml
@@ -9,6 +9,17 @@ john:
code: john-001
auth_info: cacb5b
+william:
+ name: William
+ email: william@inbox.test
+ phone: '+555.555'
+ ident: 1234
+ ident_type: priv
+ ident_country_code: US
+ registrar: bestnames
+ code: william-001
+ auth_info: 6573d0
+
jane:
name: Jane
email: jane@mail.test
diff --git a/test/fixtures/domain_contacts.yml b/test/fixtures/domain_contacts.yml
index fd60e8c99..3442278a1 100644
--- a/test/fixtures/domain_contacts.yml
+++ b/test/fixtures/domain_contacts.yml
@@ -3,6 +3,11 @@ shop_jane:
contact: jane
type: AdminDomainContact
+shop_william:
+ domain: shop
+ contact: william
+ type: TechDomainContact
+
airport_john:
domain: airport
contact: john
diff --git a/test/fixtures/domain_transfers.yml b/test/fixtures/domain_transfers.yml
new file mode 100644
index 000000000..c8b4181f2
--- /dev/null
+++ b/test/fixtures/domain_transfers.yml
@@ -0,0 +1,7 @@
+shop:
+ status: serverApproved
+ transfer_requested_at: 2010-07-05
+ transferred_at: 2010-07-05
+ domain: shop
+ old_registrar: bestnames
+ new_registrar: goodnames
diff --git a/test/fixtures/messages.yml b/test/fixtures/messages.yml
new file mode 100644
index 000000000..47cbdd0f2
--- /dev/null
+++ b/test/fixtures/messages.yml
@@ -0,0 +1,4 @@
+greeting:
+ body: Welcome!
+ queued: true
+ registrar: bestnames
diff --git a/test/integration/api/domain_transfers_test.rb b/test/integration/api/domain_transfers_test.rb
index 69d1e7d52..b90b59be4 100644
--- a/test/integration/api/domain_transfers_test.rb
+++ b/test/integration/api/domain_transfers_test.rb
@@ -1,11 +1,13 @@
require 'test_helper'
class APIDomainTransfersTest < ActionDispatch::IntegrationTest
- def test_transfers_domain
- request_params = { format: :json,
- data: { domainTransfers: [{ domainName: 'shop.test', transferCode: '65078d5' }] } }
+ def setup
+ @domain = domains(:shop)
+ Setting.transfer_wait_time = 0 # Auto-approval
+ end
+
+ def test_returns_domain_transfers
post '/repp/v1/domain_transfers', request_params, { 'HTTP_AUTHORIZATION' => http_auth_key }
- assert_equal registrars(:goodnames), domains(:shop).registrar
assert_response 200
assert_equal ({ data: [{
type: 'domain_transfer',
@@ -16,6 +18,45 @@ class APIDomainTransfersTest < ActionDispatch::IntegrationTest
JSON.parse(response.body, symbolize_names: true)
end
+ def test_creates_new_domain_transfer
+ assert_difference -> { @domain.transfers.size } do
+ post '/repp/v1/domain_transfers', request_params, { 'HTTP_AUTHORIZATION' => http_auth_key }
+ end
+ end
+
+ def test_approves_automatically_if_auto_approval_is_enabled
+ post '/repp/v1/domain_transfers', request_params, { 'HTTP_AUTHORIZATION' => http_auth_key }
+ assert @domain.transfers.last.approved?
+ end
+
+ def test_changes_registrar
+ post '/repp/v1/domain_transfers', request_params, { 'HTTP_AUTHORIZATION' => http_auth_key }
+ @domain.reload
+ assert_equal registrars(:goodnames), @domain.registrar
+ end
+
+ def test_regenerates_transfer_code
+ @old_transfer_code = @domain.transfer_code
+
+ post '/repp/v1/domain_transfers', request_params, { 'HTTP_AUTHORIZATION' => http_auth_key }
+ @domain.reload
+ refute_equal @domain.transfer_code, @old_transfer_code
+ end
+
+ def test_notifies_old_registrar
+ @old_registrar = @domain.registrar
+
+ assert_difference -> { @old_registrar.messages.count } do
+ post '/repp/v1/domain_transfers', request_params, { 'HTTP_AUTHORIZATION' => http_auth_key }
+ end
+ end
+
+ def test_duplicates_registrant_admin_and_tech_contacts
+ assert_difference 'Contact.count', 3 do
+ post '/repp/v1/domain_transfers', request_params, { 'HTTP_AUTHORIZATION' => http_auth_key }
+ end
+ end
+
def test_fails_if_domain_does_not_exist
request_params = { format: :json,
data: { domainTransfers: [{ domainName: 'non-existent.test', transferCode: 'any' }] } }
@@ -30,13 +71,18 @@ class APIDomainTransfersTest < ActionDispatch::IntegrationTest
data: { domainTransfers: [{ domainName: 'shop.test', transferCode: 'wrong' }] } }
post '/repp/v1/domain_transfers', request_params, { 'HTTP_AUTHORIZATION' => http_auth_key }
assert_response 400
- refute_equal registrars(:goodnames), domains(:shop).registrar
+ refute_equal registrars(:goodnames), @domain.registrar
assert_equal ({ errors: [{ title: 'shop.test transfer code is wrong' }] }),
JSON.parse(response.body, symbolize_names: true)
end
private
+ def request_params
+ { format: :json,
+ data: { domainTransfers: [{ domainName: 'shop.test', transferCode: '65078d5' }] } }
+ end
+
def http_auth_key
ActionController::HttpAuthentication::Basic.encode_credentials('test_goodnames', 'testtest')
end
diff --git a/test/integration/epp/domain/create/transfer_code_test.rb b/test/integration/epp/domain/create/transfer_code_test.rb
index f7d70a4ea..276386851 100644
--- a/test/integration/epp/domain/create/transfer_code_test.rb
+++ b/test/integration/epp/domain/create/transfer_code_test.rb
@@ -3,7 +3,6 @@ require 'test_helper'
class EppDomainCreateTransferCodeTest < ActionDispatch::IntegrationTest
def setup
travel_to Time.zone.parse('2010-07-05')
- login_as users(:api_bestnames)
end
def test_generates_default
@@ -27,9 +26,10 @@ class EppDomainCreateTransferCodeTest < ActionDispatch::IntegrationTest
XML
- session_id = epp_sessions(:api_bestnames).session_id
- post '/epp/command/create', { frame: request_xml }, { 'HTTP_COOKIE' => "session=#{session_id}" }
+ post '/epp/command/create', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_bestnames' }
refute_empty Domain.find_by(name: 'brandnew.test').transfer_code
+ assert_equal '1000', Nokogiri::XML(response.body).at_css('result')[:code]
+ assert_equal 1, Nokogiri::XML(response.body).css('result').size
end
def test_honors_custom
@@ -56,8 +56,9 @@ class EppDomainCreateTransferCodeTest < ActionDispatch::IntegrationTest
XML
- session_id = epp_sessions(:api_bestnames).session_id
- post '/epp/command/create', { frame: request_xml }, { 'HTTP_COOKIE' => "session=#{session_id}" }
+ post '/epp/command/create', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_bestnames' }
assert_equal '1058ad73', Domain.find_by(name: 'brandnew.test').transfer_code
+ assert_equal '1000', Nokogiri::XML(response.body).at_css('result')[:code]
+ assert_equal 1, Nokogiri::XML(response.body).css('result').size
end
end
diff --git a/test/integration/epp/domain/transfer/transfer_code_test.rb b/test/integration/epp/domain/transfer/base_test.rb
similarity index 53%
rename from test/integration/epp/domain/transfer/transfer_code_test.rb
rename to test/integration/epp/domain/transfer/base_test.rb
index 0db6ba0d6..aa9f841b6 100644
--- a/test/integration/epp/domain/transfer/transfer_code_test.rb
+++ b/test/integration/epp/domain/transfer/base_test.rb
@@ -1,20 +1,16 @@
require 'test_helper'
-class EppDomainTransferTransferCodeTest < ActionDispatch::IntegrationTest
- def setup
- login_as users(:api_goodnames)
- end
-
- def test_wrong
+class EppDomainTransferBaseTest < ActionDispatch::IntegrationTest
+ def test_non_existent_domain
request_xml = <<-XML
- shop.test
+ non-existent.test
- wrong
+ any
@@ -22,9 +18,7 @@ class EppDomainTransferTransferCodeTest < ActionDispatch::IntegrationTest
XML
- session_id = epp_sessions(:api_goodnames).session_id
- post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => "session=#{session_id}" }
- refute_equal registrars(:goodnames), domains(:shop).registrar
- assert Nokogiri::XML(response.body).at_css('result[code="2201"]')
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
+ assert_equal '2303', Nokogiri::XML(response.body).at_css('result')[:code]
end
end
diff --git a/test/integration/epp/domain/transfer/domain_transfer_test.rb b/test/integration/epp/domain/transfer/domain_transfer_test.rb
deleted file mode 100644
index 1b1e604ba..000000000
--- a/test/integration/epp/domain/transfer/domain_transfer_test.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-require 'test_helper'
-
-class EppDomainTransferTest < ActionDispatch::IntegrationTest
- def setup
- login_as users(:api_goodnames)
- end
-
- def test_successfully_transfers_domain
- request_xml = <<-XML
-
-
-
-
-
- shop.test
-
- 65078d5
-
-
-
-
-
- XML
-
- session_id = epp_sessions(:api_goodnames).session_id
- post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => "session=#{session_id}" }
- assert_equal registrars(:goodnames), domains(:shop).registrar
- assert Nokogiri::XML(response.body).at_css('result[code="1000"]')
- assert_equal 1, Nokogiri::XML(response.body).css('result').size
- end
-
- def test_non_existent_domain
- request_xml = <<-XML
-
-
-
-
-
- non-existent.test
-
- any
-
-
-
-
-
- XML
-
- session_id = epp_sessions(:api_goodnames).session_id
- post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => "session=#{session_id}" }
- assert Nokogiri::XML(response.body).at_css('result[code="2303"]')
- end
-end
diff --git a/test/integration/epp/domain/transfer/query_test.rb b/test/integration/epp/domain/transfer/query_test.rb
new file mode 100644
index 000000000..1412dd9b3
--- /dev/null
+++ b/test/integration/epp/domain/transfer/query_test.rb
@@ -0,0 +1,61 @@
+require 'test_helper'
+
+class EppDomainTransferQueryTest < ActionDispatch::IntegrationTest
+ def test_returns_domain_transfer_details
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_bestnames' }
+ xml_doc = Nokogiri::XML(response.body)
+ assert_equal '1000', xml_doc.at_css('result')[:code]
+ assert_equal 1, xml_doc.css('result').size
+ assert_equal 'shop.test', xml_doc.xpath('//domain:name', 'domain' => 'https://epp.tld.ee/schema/domain-eis-1.0.xsd').text
+ assert_equal 'serverApproved', xml_doc.xpath('//domain:trStatus', 'domain' => 'https://epp.tld.ee/schema/domain-eis-1.0.xsd').text
+ assert_equal 'goodnames', xml_doc.xpath('//domain:reID', 'domain' => 'https://epp.tld.ee/schema/domain-eis-1.0.xsd').text
+ assert_equal 'bestnames', xml_doc.xpath('//domain:acID', 'domain' => 'https://epp.tld.ee/schema/domain-eis-1.0.xsd').text
+ end
+
+ def test_wrong_transfer_code
+ request_xml = <<-XML
+
+
+
+
+
+ shop.test
+
+ wrong
+
+
+
+
+
+ XML
+
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_bestnames' }
+ assert_equal '2201', Nokogiri::XML(response.body).at_css('result')[:code]
+ end
+
+ def test_no_domain_transfer
+ domains(:shop).transfers.delete_all
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_bestnames' }
+ assert_equal '2303', Nokogiri::XML(response.body).at_css('result')[:code]
+ end
+
+ private
+
+ def request_xml
+ <<-XML
+
+
+
+
+
+ shop.test
+
+ 65078d5
+
+
+
+
+
+ XML
+ end
+end
diff --git a/test/integration/epp/domain/transfer/request_test.rb b/test/integration/epp/domain/transfer/request_test.rb
new file mode 100644
index 000000000..03c5e7daf
--- /dev/null
+++ b/test/integration/epp/domain/transfer/request_test.rb
@@ -0,0 +1,137 @@
+require 'test_helper'
+
+class EppDomainTransferRequestTest < ActionDispatch::IntegrationTest
+ def setup
+ @domain = domains(:shop)
+ Setting.transfer_wait_time = 0
+ end
+
+ def test_transfers_domain_at_once
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
+ assert_equal '1000', Nokogiri::XML(response.body).at_css('result')[:code]
+ assert_equal 1, Nokogiri::XML(response.body).css('result').size
+ end
+
+ def test_creates_new_domain_transfer
+ assert_difference -> { @domain.transfers.size } do
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
+ end
+ end
+
+ def test_approves_automatically_if_auto_approval_is_enabled
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
+ assert_equal 'serverApproved', Nokogiri::XML(response.body).xpath('//domain:trStatus', 'domain' =>
+ 'https://epp.tld.ee/schema/domain-eis-1.0.xsd').text
+ end
+
+ def test_changes_registrar
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
+ @domain.reload
+ assert_equal registrars(:goodnames), @domain.registrar
+ end
+
+ def test_regenerates_transfer_code
+ @old_transfer_code = @domain.transfer_code
+
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
+
+ @domain.reload
+ refute_equal @domain.transfer_code, @old_transfer_code
+ end
+
+ def test_notifies_old_registrar
+ @old_registrar = @domain.registrar
+
+ assert_difference -> { @old_registrar.messages.count } do
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
+ end
+ end
+
+ def test_duplicates_registrant_admin_and_tech_contacts
+ assert_difference 'Contact.count', 3 do
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
+ end
+ end
+
+ def test_saves_legal_document
+ assert_difference -> { @domain.legal_documents(true).size } do
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
+ end
+ end
+
+ def test_non_transferable_domain
+ @domain.update!(statuses: [DomainStatus::SERVER_TRANSFER_PROHIBITED])
+
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
+ domains(:shop).reload
+
+ assert_equal registrars(:bestnames), domains(:shop).registrar
+ assert_equal '2304', Nokogiri::XML(response.body).at_css('result')[:code]
+ end
+
+ def test_discarded_domain
+ @domain.update!(statuses: [DomainStatus::DELETE_CANDIDATE])
+
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
+ @domain.reload
+
+ assert_equal registrars(:bestnames), @domain.registrar
+ assert_equal '2105', Nokogiri::XML(response.body).at_css('result')[:code]
+ end
+
+ def test_same_registrar
+ assert_no_difference -> { @domain.transfers.size } do
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_bestnames' }
+ end
+
+ assert_equal '2002', Nokogiri::XML(response.body).at_css('result')[:code]
+ end
+
+ def test_wrong_transfer_code
+ request_xml = <<-XML
+
+
+
+
+
+ shop.test
+
+ wrong
+
+
+
+
+
+ XML
+
+ post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
+ @domain.reload
+ refute_equal registrars(:goodnames), @domain.registrar
+ assert_equal '2201', Nokogiri::XML(response.body).at_css('result')[:code]
+ end
+
+ private
+
+ def request_xml
+ <<-XML
+
+
+
+
+
+ shop.test
+
+ 65078d5
+
+
+
+
+
+ test
+
+
+
+
+ XML
+ end
+end
diff --git a/test/integration/epp/domain/update/transfer_code_test.rb b/test/integration/epp/domain/update/transfer_code_test.rb
index 6208c2899..92ee58a02 100644
--- a/test/integration/epp/domain/update/transfer_code_test.rb
+++ b/test/integration/epp/domain/update/transfer_code_test.rb
@@ -1,10 +1,6 @@
require 'test_helper'
class EppDomainUpdateTest < ActionDispatch::IntegrationTest
- def setup
- login_as users(:api_bestnames)
- end
-
def test_overwrites_existing
request_xml = <<-XML
@@ -24,8 +20,9 @@ class EppDomainUpdateTest < ActionDispatch::IntegrationTest
XML
- session_id = epp_sessions(:api_bestnames).session_id
- post '/epp/command/update', { frame: request_xml }, { 'HTTP_COOKIE' => "session=#{session_id}" }
+ post '/epp/command/update', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_bestnames' }
assert_equal 'f0ff7d17b0', domains(:shop).transfer_code
+ assert_equal '1000', Nokogiri::XML(response.body).at_css('result')[:code]
+ assert_equal 1, Nokogiri::XML(response.body).css('result').size
end
end
diff --git a/test/integration/epp/poll_test.rb b/test/integration/epp/poll_test.rb
new file mode 100644
index 000000000..db6091cb0
--- /dev/null
+++ b/test/integration/epp/poll_test.rb
@@ -0,0 +1,30 @@
+require 'test_helper'
+
+class EppPollTest < ActionDispatch::IntegrationTest
+ def test_messages
+ post '/epp/command/poll', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_bestnames' }
+ assert_equal '1301', Nokogiri::XML(response.body).at_css('result')[:code]
+ assert_equal 1, Nokogiri::XML(response.body).css('msgQ').size
+ assert_equal 1, Nokogiri::XML(response.body).css('result').size
+ end
+
+ def test_no_messages
+ registrars(:bestnames).messages.delete_all(:delete_all)
+ post '/epp/command/poll', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_bestnames' }
+ assert_equal '1300', Nokogiri::XML(response.body).at_css('result')[:code]
+ assert_equal 1, Nokogiri::XML(response.body).css('result').size
+ end
+
+ private
+
+ def request_xml
+ <<-XML
+
+
+
+
+
+
+ XML
+ end
+end
diff --git a/test/models/domain/domain_transfer_test.rb b/test/models/domain/transferable_test.rb
similarity index 72%
rename from test/models/domain/domain_transfer_test.rb
rename to test/models/domain/transferable_test.rb
index ad8088718..42613aa45 100644
--- a/test/models/domain/domain_transfer_test.rb
+++ b/test/models/domain/transferable_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class DomainTransferTest < ActiveSupport::TestCase
+class DomainTransferableTest < ActiveSupport::TestCase
def setup
@domain = domains(:shop)
@new_registrar = registrars(:goodnames)
@@ -44,22 +44,4 @@ class DomainTransferTest < ActiveSupport::TestCase
@domain.transfer(@new_registrar)
refute_same old_transfer_code, @domain.transfer_code
end
-
- def test_creates_domain_transfer
- assert_difference 'DomainTransfer.count' do
- @domain.transfer(@new_registrar)
- end
- end
-
- def test_creates_message
- assert_difference 'Message.count' do
- @domain.transfer(@new_registrar)
- end
- end
-
- def test_copies_contacts
- assert_difference 'Contact.count', 2 do
- @domain.transfer(@new_registrar)
- end
- end
end
diff --git a/test/models/domain_transfer_test.rb b/test/models/domain_transfer_test.rb
new file mode 100644
index 000000000..7f11caf80
--- /dev/null
+++ b/test/models/domain_transfer_test.rb
@@ -0,0 +1,32 @@
+require 'test_helper'
+
+class DomainTransferTest < ActiveSupport::TestCase
+ def setup
+ @domain_transfer = domain_transfers(:shop)
+ end
+
+ def test_approval
+ @domain_transfer.approve
+ @domain_transfer.reload
+ assert @domain_transfer.approved?
+ end
+
+ def test_notifies_old_registrar_on_approval
+ old_registrar = @domain_transfer.old_registrar
+
+ assert_difference -> { old_registrar.messages.count } do
+ @domain_transfer.approve
+ end
+
+ body = 'Transfer of domain shop.test has been approved.' \
+ ' It was associated with registrant john-001' \
+ ' and contacts jane-001, william-001.'
+ id = @domain_transfer.id
+ class_name = @domain_transfer.class.name
+
+ message = old_registrar.messages.last
+ assert_equal body, message.body
+ assert_equal id, message.attached_obj_id
+ assert_equal class_name, message.attached_obj_type
+ end
+end
diff --git a/test/models/message_test.rb b/test/models/message_test.rb
new file mode 100644
index 000000000..1c7c7bad1
--- /dev/null
+++ b/test/models/message_test.rb
@@ -0,0 +1,21 @@
+require 'test_helper'
+
+class MessageTest < ActiveSupport::TestCase
+ def setup
+ @message = messages(:greeting)
+ end
+
+ def test_valid
+ assert @message.valid?
+ end
+
+ def test_invalid_without_body
+ @message.body = nil
+ assert @message.invalid?
+ end
+
+ def test_invalid_without_registrar
+ @message.registrar = nil
+ assert @message.invalid?
+ end
+end