diff --git a/app/controllers/api/v1/registrant/contacts_controller.rb b/app/controllers/api/v1/registrant/contacts_controller.rb index 8e8b46631..b196c567a 100644 --- a/app/controllers/api/v1/registrant/contacts_controller.rb +++ b/app/controllers/api/v1/registrant/contacts_controller.rb @@ -34,15 +34,15 @@ module Api end end - def do_need_update_contact - result = current_registrant_user.do_need_update_contact? + def do_need_update_contacts + result = current_registrant_user.do_need_update_contacts? render json: { update_contacts: result[:result], counter: result[:counter] } end - def update_company_contacts - companies = current_registrant_user.update_company_contacts + def update_contacts + contacts = current_registrant_user.update_contacts - render json: { message: 'get it', companies: companies } + render json: { message: 'get it', contacts: contacts } end def update diff --git a/app/models/ability.rb b/app/models/ability.rb index baa26e4cb..caca24524 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -12,7 +12,7 @@ class Ability @user.roles&.each { |role| send(role) } when 'ApiUser' @user.roles&.each { |role| send(role) } - when 'RegistrantUser' + when 'RegistrantUser' static_registrant end diff --git a/app/models/action.rb b/app/models/action.rb index ac5ee7f72..8a822f867 100644 --- a/app/models/action.rb +++ b/app/models/action.rb @@ -2,18 +2,40 @@ class Action < ApplicationRecord has_paper_trail versions: { class_name: 'Version::ActionVersion' } belongs_to :user - belongs_to :contact + belongs_to :contact, optional: true + has_many :subactions, class_name: 'Action', + foreign_key: 'bulk_action_id', + inverse_of: :bulk_action, + dependent: :destroy + belongs_to :bulk_action, class_name: 'Action', optional: true validates :operation, inclusion: { in: proc { |action| action.class.valid_operations } } class << self def valid_operations - %w[update] + %w[update bulk_update] end end def notification_key - raise 'Action object is missing' unless contact + raise 'Action object is missing' unless bulk_action? || contact + "contact_#{operation}".to_sym end + + def bulk_action? + !!subactions.exists? + end + + def to_non_available_contact_codes + return [] unless bulk_action? + + subactions.map do |a| + { + code: a.contact.code, + avail: 0, + reason: 'in use', + } + end + end end diff --git a/app/models/bulk_action.rb b/app/models/bulk_action.rb new file mode 100644 index 000000000..9c98ee2db --- /dev/null +++ b/app/models/bulk_action.rb @@ -0,0 +1 @@ +class BulkAction < Action; end diff --git a/app/models/contact.rb b/app/models/contact.rb index dab2dd6d9..676b0da87 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -30,6 +30,19 @@ class Contact < ApplicationRecord .where('success = false and verified_at IS NOT NULL') } + scope :with_different_company_name, (lambda do |company| + where("ident = ? AND ident_country_code = 'EE' AND name != ?", + company.registration_number, + company.company_name) + end) + + scope :with_different_registrant_name, (lambda do |user| + where('ident = ? AND ident_country_code = ? AND UPPER(name) != UPPER(?)', + user.ident, + user.country.alpha2, + user.username) + end) + NAME_REGEXP = /([\u00A1-\u00B3\u00B5-\u00BF\u0021-\u0026\u0028-\u002C\u003A-\u0040]| [\u005B-\u005F\u007B-\u007E\u2040-\u206F\u20A0-\u20BF\u2100-\u218F])/x diff --git a/app/models/epp/contact.rb b/app/models/epp/contact.rb index 614be201b..35691d789 100644 --- a/app/models/epp/contact.rb +++ b/app/models/epp/contact.rb @@ -47,7 +47,7 @@ class Epp::Contact < Contact codes = codes.map { |c| c.include?(':') ? c : "#{reg}:#{c}" } res = [] - codes.map { |c| c.include?(':') ? c : "#{reg}:#{c}" }.map { |c| c.strip.upcase }.each do |x| + codes.map { |c| c.strip.upcase }.each do |x| c = find_by_epp_code(x) res << (c ? { code: c.code, avail: 0, reason: 'in use' } : { code: x, avail: 1 }) end diff --git a/app/models/notification.rb b/app/models/notification.rb index 07e824367..c9af66c56 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -2,7 +2,7 @@ class Notification < ApplicationRecord include Versions # version/notification_version.rb belongs_to :registrar - belongs_to :action + belongs_to :action, optional: true scope :unread, -> { where(read: false) } diff --git a/app/models/registrant_user.rb b/app/models/registrant_user.rb index 80b8ecab9..073ab3214 100644 --- a/app/models/registrant_user.rb +++ b/app/models/registrant_user.rb @@ -26,13 +26,13 @@ class RegistrantUser < User [] end - def do_need_update_contact? - return { result: false, counter: 0 } if companies.blank? - + def do_need_update_contacts? counter = 0 + + counter += Contact.with_different_registrant_name(self).size + companies.each do |company| - counter += Contact.where(ident: company.registration_number, ident_country_code: 'EE')&. - reject { |contact| contact.name == company.company_name }.size + counter += Contact.with_different_company_name(company).size end return { result: true, counter: counter } if counter.positive? @@ -40,40 +40,25 @@ class RegistrantUser < User { result: false, counter: 0 } end - def update_company_contacts - return [] if companies.blank? - + # rubocop:disable Metrics/MethodLength + def update_contacts + user = self + contacts = [] + contacts.concat(Contact.with_different_registrant_name(user).each do |c| + c.write_attribute(:name, user.username) + end) companies.each do |company| - contacts = Contact.where(ident: company.registration_number, ident_country_code: 'EE') - - next if contacts.blank? - - contacts.each do |contact| - next if company.company_name == contact.name - - update_company_name(contact: contact, company: company) - end + contacts.concat(Contact.with_different_company_name(company).each do |c| + c.write_attribute(:name, company.company_name) + end) end - companies - end - - def update_company_name(contact:, company:) - old_contact_name = contact.name - contact.name = company.company_name - - contact.save(validate: false) - - notify_registrar_data_updated(company_name: company.company_name, - old_contact_name: old_contact_name, - contact: contact) - end - - def notify_registrar_data_updated(company_name:, old_contact_name:, contact:) - contact.registrar.notifications.create!( - text: "Contact update: #{contact.id} name updated from #{old_contact_name} to #{company_name} by the registry" - ) + return [] if contacts.blank? + + group_and_bulk_update(contacts) + contacts end + # rubocop:enable Metrics/MethodLength def contacts(representable: true) Contact.registrant_user_contacts(self, representable: representable) @@ -111,17 +96,6 @@ class RegistrantUser < User username.split.second end - def update_related_contacts - contacts = Contact.where(ident: ident, ident_country_code: country.alpha2) - .where('UPPER(name) != UPPER(?)', username) - - contacts.each do |contact| - contact.update(name: username) - action = actions.create!(contact: contact, operation: :update) - contact.registrar.notify(action) - end - end - class << self def find_or_create_by_api_data(user_data = {}) return false unless user_data[:ident] @@ -158,9 +132,27 @@ class RegistrantUser < User user = find_or_create_by(registrant_ident: "#{user_data[:country_code]}-#{user_data[:ident]}") user.username = "#{user_data[:first_name]} #{user_data[:last_name]}" user.save - - user.update_related_contacts user end end + + private + + def group_and_bulk_update(contacts) + contacts.group_by(&:registrar_id).each do |registrar_id, reg_contacts| + bulk_action, action = actions.create!(operation: :bulk_update) if reg_contacts.size > 1 + reg_contacts.each do |c| + if c.save(validate: false) + action = actions.create!(contact: c, operation: :update, bulk_action_id: bulk_action&.id) + end + end + notify_registrar_contacts_updated(action: bulk_action || action, + registrar_id: registrar_id) + end + end + + def notify_registrar_contacts_updated(action:, registrar_id:) + registrar = Registrar.find(registrar_id) + registrar&.notify(action) + end end diff --git a/app/models/registrar.rb b/app/models/registrar.rb index 8517bd6fe..d7ba62306 100644 --- a/app/models/registrar.rb +++ b/app/models/registrar.rb @@ -218,8 +218,15 @@ class Registrar < ApplicationRecord end def notify(action) - text = I18n.t("notifications.texts.#{action.notification_key}", contact: action.contact.code) - notifications.create!(text: text) + text = I18n.t("notifications.texts.#{action.notification_key}", contact: action.contact&.code, + count: action.subactions&.count) + if action.bulk_action? + notifications.create!(text: text, action_id: action.id, + attached_obj_type: 'BulkAction', + attached_obj_id: action.id) + else + notifications.create!(text: text) + end end def e_invoice_iban diff --git a/app/views/epp/contacts/check.xml.builder b/app/views/epp/contacts/check.xml.builder index 6b4ea4cc7..f3b1f555a 100644 --- a/app/views/epp/contacts/check.xml.builder +++ b/app/views/epp/contacts/check.xml.builder @@ -5,15 +5,7 @@ xml.epp_head do end xml.resData do - xml.tag!('contact:chkData', 'xmlns:contact' => - Xsd::Schema.filename(for_prefix: 'contact-ee', for_version: '1.1')) do - @results.each do |result| - xml.tag!('contact:cd') do - xml.tag! "contact:id", result[:code], avail: result[:avail] - xml.tag!('contact:reason', result[:reason]) unless result[:avail] == 1 - end - end - end + xml << render('epp/contacts/partials/check', builder: xml, results: @results) end render('epp/shared/trID', builder: xml) diff --git a/app/views/epp/contacts/partials/_check.xml.builder b/app/views/epp/contacts/partials/_check.xml.builder new file mode 100644 index 000000000..70bb1f4e3 --- /dev/null +++ b/app/views/epp/contacts/partials/_check.xml.builder @@ -0,0 +1,9 @@ +builder.tag!('contact:chkData', 'xmlns:contact' => + Xsd::Schema.filename(for_prefix: 'contact-ee', for_version: '1.1')) do + results.each do |result| + builder.tag!('contact:cd') do + builder.tag! 'contact:id', result[:code], avail: result[:avail] + # builder.tag!('contact:reason', result[:reason]) unless result[:avail] == 1 + end + end +end diff --git a/app/views/epp/poll/_action.xml.builder b/app/views/epp/poll/_action.xml.builder deleted file mode 100644 index dc0adb4e4..000000000 --- a/app/views/epp/poll/_action.xml.builder +++ /dev/null @@ -1,9 +0,0 @@ -builder.extension do - builder.tag!('changePoll:changeData', - 'xmlns:changePoll' => Xsd::Schema.filename(for_prefix: 'changePoll')) do - builder.tag!('changePoll:operation', action.operation) - builder.tag!('changePoll:date', action.created_at.utc.xmlschema) - builder.tag!('changePoll:svTRID', action.id) - builder.tag!('changePoll:who', action.user) - end -end diff --git a/app/views/epp/poll/_extension.xml.builder b/app/views/epp/poll/_extension.xml.builder new file mode 100644 index 000000000..5a17995df --- /dev/null +++ b/app/views/epp/poll/_extension.xml.builder @@ -0,0 +1,21 @@ +builder.extension do + builder.tag!('changePoll:changeData', + 'xmlns:changePoll' => Xsd::Schema.filename(for_prefix: 'changePoll', + for_version: '1.0')) do + case type + when 'action' + builder.tag!('changePoll:operation', obj.operation) + builder.tag!('changePoll:date', obj.created_at.utc.xmlschema) + builder.tag!('changePoll:svTRID', obj.id) + builder.tag!('changePoll:who', obj.user) + if obj.bulk_action? + builder.tag!( + 'changePoll:reason', + 'Auto-update according to official data' + ) + end + when 'state' + builder.tag!('changePoll:operation', obj) + end + end +end diff --git a/app/views/epp/poll/poll_req.xml.builder b/app/views/epp/poll/poll_req.xml.builder index a1f12fd65..0a916e6ad 100644 --- a/app/views/epp/poll/poll_req.xml.builder +++ b/app/views/epp/poll/poll_req.xml.builder @@ -9,27 +9,35 @@ xml.epp_head do xml.msg @notification.text end - if @notification.attached_obj_type == 'DomainTransfer' && @object - xml.resData do - xml << render('epp/domains/partials/transfer', builder: xml, dt: @object) + if @object + case @notification.attached_obj_type + when 'DomainTransfer' + xml.resData do + xml << render('epp/domains/partials/transfer', builder: xml, dt: @object) + end + when 'BulkAction' + xml.resData do + xml << render( + 'epp/contacts/partials/check', + builder: xml, + results: @object.to_non_available_contact_codes + ) + end end end - if @notification.action&.contact || @notification.registry_lock? + if @notification.action || @notification.registry_lock? if @notification.registry_lock? state = @notification.text.include?('unlocked') ? 'unlock' : 'lock' - xml.extension do - xml.tag!('changePoll:changeData', - 'xmlns:changePoll': Xsd::Schema.filename(for_prefix: 'changePoll')) do - xml.tag!('changePoll:operation', state) - end - end + render(partial: 'epp/poll/extension', + locals: { builder: xml, + obj: state, + type: 'state' }) else - render(partial: 'epp/poll/action', - locals: { - builder: xml, - action: @notification.action, - }) + render(partial: 'epp/poll/extension', + locals: { builder: xml, + obj: @notification.action, + type: 'action' }) end end diff --git a/config/locales/notifications.en.yml b/config/locales/notifications.en.yml index b5c1dfd47..3bd65ea7e 100644 --- a/config/locales/notifications.en.yml +++ b/config/locales/notifications.en.yml @@ -6,6 +6,7 @@ en: It was associated with registrant %{old_registrant_code} and contacts %{old_contacts_codes}. contact_update: Contact %{contact} has been updated by registrant + contact_bulk_update: '%{count} contacts have been updated by registrant' csync: CSYNC DNSSEC %{action} for domain %{domain} registrar_locked: Domain %{domain_name} has been locked by registrant registrar_unlocked: Domain %{domain_name} has been unlocked by registrant diff --git a/config/routes.rb b/config/routes.rb index 79807729a..a2a4556f7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -129,8 +129,9 @@ Rails.application.routes.draw do resource :registry_lock, only: %i[create destroy] end resources :contacts, only: %i[index show update], param: :uuid do - get 'do_need_update_contact', to: 'contacts#do_need_update_contact', as: :do_need_update_contact - post 'update_company_contacts', to: 'contacts#update_company_contacts', as: :update_company_contacts + get 'do_need_update_contacts', to: 'contacts#do_need_update_contacts', + as: :do_need_update_contacts + post 'update_contacts', to: 'contacts#update_contacts', as: :update_contacts end resources :companies, only: %i[index] end diff --git a/db/migrate/20220316140727_add_bulk_actions.rb b/db/migrate/20220316140727_add_bulk_actions.rb new file mode 100644 index 000000000..1eae94220 --- /dev/null +++ b/db/migrate/20220316140727_add_bulk_actions.rb @@ -0,0 +1,5 @@ +class AddBulkActions < ActiveRecord::Migration[6.1] + def change + add_column :actions, :bulk_action_id, :integer, default: nil + end +end diff --git a/db/structure.sql b/db/structure.sql index 0c8420f43..984a949df 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -304,7 +304,8 @@ CREATE TABLE public.actions ( user_id integer, operation character varying NOT NULL, created_at timestamp without time zone, - contact_id integer + contact_id integer, + bulk_action_id integer ); @@ -826,8 +827,7 @@ CREATE TABLE public.dnskeys ( updator_str character varying, legacy_domain_id integer, updated_at timestamp without time zone, - validation_datetime timestamp without time zone, - failed_validation_reason character varying + validation_datetime timestamp without time zone ); @@ -1195,7 +1195,6 @@ CREATE TABLE public.invoices ( buyer_vat_no character varying, issue_date date NOT NULL, e_invoice_sent_at timestamp without time zone, - payment_link character varying, CONSTRAINT invoices_due_date_is_not_before_issue_date CHECK ((due_date >= issue_date)) ); @@ -5402,8 +5401,6 @@ INSERT INTO "schema_migrations" (version) VALUES ('20220106123143'), ('20220113201642'), ('20220113220809'), -('20220124105717'), -('20220216113112'), -('20220228093211'); +('20220316140727'); diff --git a/test/fixtures/actions.yml b/test/fixtures/actions.yml index 46736e0a1..b802679ba 100644 --- a/test/fixtures/actions.yml +++ b/test/fixtures/actions.yml @@ -2,4 +2,24 @@ contact_update: operation: update contact: john created_at: <%= Time.zone.parse('2010-07-05').to_s(:db) %> - user: registrant \ No newline at end of file + user: registrant + +contacts_update_bulk_action: + operation: bulk_update + user: registrant + +contact_update_subaction_one: + operation: update + contact: william + created_at: <%= Time.zone.parse('2010-07-05').to_s(:db) %> + user: registrant + bulk_action: contacts_update_bulk_action + +contact_update_subaction_two: + operation: update + contact: jane + created_at: <%= Time.zone.parse('2010-07-05').to_s(:db) %> + user: registrant + bulk_action: contacts_update_bulk_action + + diff --git a/test/integration/epp/contact/check/base_test.rb b/test/integration/epp/contact/check/base_test.rb index f1b9f4d16..6ad027fc6 100644 --- a/test/integration/epp/contact/check/base_test.rb +++ b/test/integration/epp/contact/check/base_test.rb @@ -76,7 +76,7 @@ class EppContactCheckBaseTest < EppTestCase response_xml = Nokogiri::XML(response.body) assert_correct_against_schema response_xml assert_equal '0', response_xml.at_xpath('//contact:id', contact: xml_schema)['avail'] - assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text + # assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text end def test_multiple_contacts @@ -127,7 +127,7 @@ class EppContactCheckBaseTest < EppTestCase assert_correct_against_schema response_xml assert_epp_response :completed_successfully assert_equal "#{@contact.registrar.code}:JOHN-001".upcase, response_xml.at_xpath('//contact:id', contact: xml_schema).text - assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text + # assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text end def test_check_contact_without_prefix @@ -154,7 +154,7 @@ class EppContactCheckBaseTest < EppTestCase assert_correct_against_schema response_xml assert_epp_response :completed_successfully assert_equal "#{@contact.registrar.code}:JOHN-001".upcase, response_xml.at_xpath('//contact:id', contact: xml_schema).text - assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text + # assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text end private diff --git a/test/integration/epp/poll_test.rb b/test/integration/epp/poll_test.rb index 5cdb7e524..29c24af26 100644 --- a/test/integration/epp/poll_test.rb +++ b/test/integration/epp/poll_test.rb @@ -7,16 +7,8 @@ class EppPollTest < EppTestCase # Deliberately does not conform to RFC5730, which requires the first notification to be returned def test_return_latest_notification_when_queue_is_not_empty - request_xml = <<-XML - - - - - - - XML - post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + post epp_poll_path, params: { frame: request_req_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } xml_doc = Nokogiri::XML(response.body) assert_epp_response :completed_successfully_ack_to_dequeue @@ -30,17 +22,9 @@ class EppPollTest < EppTestCase version = Version::DomainVersion.last @notification.update(attached_obj_type: 'DomainVersion', attached_obj_id: version.id) - request_xml = <<-XML - - - - - - - XML assert_nothing_raised do - post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + post epp_poll_path, params: { frame: request_req_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } end xml_doc = Nokogiri::XML(response.body) @@ -54,19 +38,11 @@ class EppPollTest < EppTestCase def test_return_action_data_when_present @notification.update!(action: actions(:contact_update)) - request_xml = <<-XML - - - - - - - XML - post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + post epp_poll_path, params: { frame: request_req_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } xml_doc = Nokogiri::XML(response.body) - namespace = Xsd::Schema.filename(for_prefix: 'changePoll') + namespace = Xsd::Schema.filename(for_prefix: 'changePoll', for_version: '1.0') assert_equal 'update', xml_doc.xpath('//changePoll:operation', 'changePoll' => namespace).text assert_equal Time.zone.parse('2010-07-05').utc.xmlschema, xml_doc.xpath('//changePoll:date', 'changePoll' => namespace).text @@ -76,19 +52,35 @@ class EppPollTest < EppTestCase 'changePoll' => namespace).text end + def test_return_notifcation_with_bulk_action_data + bulk_action = actions(:contacts_update_bulk_action) + @notification.update!(action: bulk_action, + attached_obj_id: bulk_action.id, + attached_obj_type: 'BulkAction') + + post epp_poll_path, params: { frame: request_req_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + + xml_doc = Nokogiri::XML(response.body) + namespace = Xsd::Schema.filename(for_prefix: 'changePoll', for_version: '1.0') + + assert_equal 2, xml_doc.xpath('//contact:cd', contact: xml_schema).size + assert_epp_response :completed_successfully_ack_to_dequeue + assert_equal 'bulk_update', xml_doc.xpath('//changePoll:operation', + 'changePoll' => namespace).text + assert_equal @notification.action.id.to_s, xml_doc.xpath('//changePoll:svTRID', + 'changePoll' => namespace).text + assert_equal 'Registrant User', xml_doc.xpath('//changePoll:who', + 'changePoll' => namespace).text + assert_equal 'Auto-update according to official data', + xml_doc.xpath('//changePoll:reason', 'changePoll' => namespace).text + end + def test_no_notifications registrars(:bestnames).notifications.delete_all(:delete_all) - request_xml = <<-XML - - - - - - - XML - post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + post epp_poll_path, params: { frame: request_req_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } assert_epp_response :completed_successfully_no_messages end @@ -106,7 +98,7 @@ class EppPollTest < EppTestCase XML post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } notification.reload xml_doc = Nokogiri::XML(response.body) @@ -128,7 +120,7 @@ class EppPollTest < EppTestCase XML post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } notification.reload assert notification.unread? @@ -145,13 +137,22 @@ class EppPollTest < EppTestCase XML post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } assert_epp_response :object_does_not_exist end def test_anonymous_user_cannot_access - request_xml = <<-XML + post '/epp/command/poll', params: { frame: request_req_xml }, + headers: { 'HTTP_COOKIE' => 'session=non-existent' } + + assert_epp_response :authorization_error + end + + private + + def request_req_xml + <<-XML @@ -159,10 +160,9 @@ class EppPollTest < EppTestCase XML + end - post '/epp/command/poll', params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=non-existent' } - - assert_epp_response :authorization_error + def xml_schema + Xsd::Schema.filename(for_prefix: 'contact-ee', for_version: '1.1') end end diff --git a/test/models/registrant_user/registrant_user_creation_test.rb b/test/models/registrant_user/registrant_user_creation_test.rb index 9fff4ca02..a32191db8 100644 --- a/test/models/registrant_user/registrant_user_creation_test.rb +++ b/test/models/registrant_user/registrant_user_creation_test.rb @@ -7,42 +7,26 @@ class RegistrantUserCreationTest < ActiveSupport::TestCase first_name: 'JOHN', last_name: 'SMITH' } - - RegistrantUser.find_or_create_by_api_data(user_data) + assert_difference 'RegistrantUser.count' do + RegistrantUser.find_or_create_by_api_data(user_data) + end user = User.find_by(registrant_ident: 'EE-37710100070') assert_equal('JOHN SMITH', user.username) end - def test_find_or_create_by_api_data_creates_a_user_with_original_name + def test_find_or_create_by_api_data_updates_a_user_with_existing_ident user_data = { - ident: '37710100070', + ident: '1234', + country_code: 'US', first_name: 'John', - last_name: 'Smith' + last_name: 'Smith', } + assert_no_difference 'RegistrantUser.count' do + RegistrantUser.find_or_create_by_api_data(user_data) + end - RegistrantUser.find_or_create_by_api_data(user_data) - - user = User.find_by(registrant_ident: 'EE-37710100070') + user = User.find_by(registrant_ident: 'US-1234') assert_equal('John Smith', user.username) end - - def test_updates_related_contacts_name_if_differs_from_e_identity - contact = contacts(:john) - contact.update(ident: '39708290276', ident_country_code: 'EE') - - user_data = { - ident: '39708290276', - first_name: 'John', - last_name: 'Doe' - } - - RegistrantUser.find_or_create_by_api_data(user_data) - - user = User.find_by(registrant_ident: 'EE-39708290276') - assert_equal('John Doe', user.username) - - contact.reload - assert_equal user.username, contact.name - end end diff --git a/test/models/registrant_user_test.rb b/test/models/registrant_user_test.rb index 2b1d6a880..81e57fa72 100644 --- a/test/models/registrant_user_test.rb +++ b/test/models/registrant_user_test.rb @@ -32,30 +32,61 @@ class RegistrantUserTest < ActiveSupport::TestCase assert_equal Country.new('US'), user.country end - def test_should_update_org_contact_if_data_from_business_registry_dismatch + def test_should_update_contacts_if_names_dismatch assert_equal 'US-1234', @user.registrant_ident - org = contacts(:acme_ltd) - org.ident_country_code = 'EE' - org.save(validate: false) - org.reload + registrars = [registrars(:bestnames), registrars(:goodnames)] + contacts = [contacts(:john), contacts(:william), contacts(:identical_to_william), + contacts(:acme_ltd), contacts(:registrar_ltd)] + contacts.each do |c| + if c.ident_type == 'priv' + c.ident = @user.ident + else + c.ident_country_code = 'EE' + c.registrar = registrars(:bestnames) + end + c.save(validate: false) + end - company = Company.new(org.ident, "ace") + company_one = Company.new(contacts(:acme_ltd).ident, 'ace') + company_two = Company.new(contacts(:registrar_ltd).ident, 'acer') - Spy.on(@user, :companies).and_return([company]) - @user.update_company_contacts - org.reload + Spy.on(@user, :companies).and_return([company_one, company_two]) + @user.update_contacts - assert_equal org.name, company.company_name + contacts.each do |c| + c.reload + assert_equal @user.username, c.name if c.ident_type == 'priv' + assert @user.actions.find_by(operation: :update, contact_id: c.id) + end + + bulk_action = @user.actions.where(operation: :bulk_update).last + + assert_equal 4, bulk_action.subactions.size + + registrars.each do |r| + notification = r.notifications.unread.order('created_at DESC').take + if r == registrars(:bestnames) + assert_equal '4 contacts have been updated by registrant', notification.text + assert_equal 'BulkAction', notification.attached_obj_type + assert_equal bulk_action.id, notification.attached_obj_id + assert_equal bulk_action.id, notification.action_id + else + assert_equal 'Contact william-002 has been updated by registrant', notification.text + refute notification.action_id + refute notification.attached_obj_id + refute notification.attached_obj_type + end + end end def test_queries_company_register_for_associated_companies assert_equal 'US-1234', @user.registrant_ident - company = Company.new("acme", "ace") + company = Company.new('acme', 'ace') company_register = Minitest::Mock.new company_register.expect(:representation_rights, [company], [{ citizen_personal_code: '1234', - citizen_country_code: 'USA' }]) + citizen_country_code: 'USA' }]) assert_equal [company], @user.companies(company_register) company_register.verify @@ -63,58 +94,71 @@ class RegistrantUserTest < ActiveSupport::TestCase def test_should_return_zero_count_of_companies assert_equal 'US-1234', @user.registrant_ident - org = contacts(:acme_ltd) - org.ident_country_code = 'EE' - org.save(validate: false) - org.reload + contacts = [contacts(:john), contacts(:william), contacts(:identical_to_william), + contacts(:acme_ltd), contacts(:registrar_ltd)] - company_one = Company.new(org.ident, 'Acme Ltd') + contacts.each do |c| + if c.ident_type == 'priv' + c.ident = @user.ident + c.name = @user.username + else + c.ident_country_code = 'EE' + end + c.save(validate: false) + end - Spy.on(@user, :companies).and_return([company_one]) - response = @user.do_need_update_contact? - org.reload + company_one = Company.new(contacts(:acme_ltd).ident, 'Acme Ltd') + company_two = Company.new(contacts(:registrar_ltd).ident, 'Registrar Ltd') + + Spy.on(@user, :companies).and_return([company_one, company_two]) + response = @user.do_need_update_contacts? assert_equal response[:counter], 0 end - def test_should_return_count_of_contact_which_should_be_updated + def test_should_return_count_of_contacts_which_should_be_updated assert_equal 'US-1234', @user.registrant_ident - org = contacts(:acme_ltd) - org.ident_country_code = 'EE' - org.save(validate: false) - org.reload + contacts = [contacts(:john), contacts(:william), contacts(:identical_to_william), + contacts(:acme_ltd), contacts(:registrar_ltd)] + contacts.each do |c| + if c.ident_type == 'priv' + c.ident = @user.ident + else + c.ident_country_code = 'EE' + end + c.save(validate: false) + end - company_one = Company.new(org.ident, 'ace') - company_two = Company.new(org.ident, 'acer') + company_one = Company.new(contacts(:acme_ltd).ident, 'ace') + company_two = Company.new(contacts(:registrar_ltd).ident, 'acer') Spy.on(@user, :companies).and_return([company_one, company_two]) - response = @user.do_need_update_contact? - org.reload + response = @user.do_need_update_contacts? - assert_equal response[:counter], 2 + assert_equal response[:counter], 5 end def test_returns_contacts - Contact.stub(:registrant_user_contacts, %w(john jane)) do - assert_equal %w(john jane), @user.contacts + Contact.stub(:registrant_user_contacts, %w[john jane]) do + assert_equal %w[john jane], @user.contacts end end def test_returns_direct_contacts - Contact.stub(:registrant_user_direct_contacts, %w(john jane)) do - assert_equal %w(john jane), @user.direct_contacts + Contact.stub(:registrant_user_direct_contacts, %w[john jane]) do + assert_equal %w[john jane], @user.direct_contacts end end def test_returns_domains - Domain.stub(:registrant_user_domains, %w(shop airport)) do - assert_equal %w(shop airport), @user.domains + Domain.stub(:registrant_user_domains, %w[shop airport]) do + assert_equal %w[shop airport], @user.domains end end def test_returns_administered_domains - Domain.stub(:registrant_user_administered_domains, %w(shop airport)) do - assert_equal %w(shop airport), @user.administered_domains + Domain.stub(:registrant_user_administered_domains, %w[shop airport]) do + assert_equal %w[shop airport], @user.administered_domains end end end