mirror of
https://github.com/internetee/registry.git
synced 2025-06-12 15:44:45 +02:00
Add first version of admin bulk change
This commit is contained in:
parent
efdb445488
commit
f3f89bedd7
5 changed files with 96 additions and 28 deletions
40
app/controllers/repp/v1/domains/admin_contacts_controller.rb
Normal file
40
app/controllers/repp/v1/domains/admin_contacts_controller.rb
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
module Repp
|
||||||
|
module V1
|
||||||
|
module Domains
|
||||||
|
class AdminContactsController < BaseController
|
||||||
|
before_action :set_current_contact, only: [:update]
|
||||||
|
before_action :set_new_contact, only: [:update]
|
||||||
|
|
||||||
|
def set_current_contact
|
||||||
|
@current_contact = current_user.registrar.contacts.find_by!(code: contact_params[:current_contact_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_new_contact
|
||||||
|
@new_contact = current_user.registrar.contacts.find_by!(code: params[:new_contact_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@epp_errors ||= []
|
||||||
|
@epp_errors << { code: 2304, msg: 'New contact must be valid' } if @new_contact.invalid?
|
||||||
|
|
||||||
|
unless @new_contact.identical_to?(@current_contact)
|
||||||
|
@epp_errors << { code: 2304, msg: 'Admin contacts must be identical' }
|
||||||
|
end
|
||||||
|
|
||||||
|
return handle_errors if @epp_errors.any?
|
||||||
|
|
||||||
|
affected, skipped = AdminDomainContact.replace(@current_contact, @new_contact)
|
||||||
|
@response = { affected_domains: affected, skipped_domains: skipped }
|
||||||
|
render_success(data: @response)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def contact_params
|
||||||
|
params.require(%i[current_contact_id new_contact_id])
|
||||||
|
params.permit(:current_contact_id, :new_contact_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,2 +1,23 @@
|
||||||
class AdminDomainContact < DomainContact
|
class AdminDomainContact < DomainContact
|
||||||
|
def self.replace(current_contact, new_contact)
|
||||||
|
affected_domains = []
|
||||||
|
skipped_domains = []
|
||||||
|
admin_contacts = where(contact: current_contact)
|
||||||
|
|
||||||
|
admin_contacts.each do |admin_contact|
|
||||||
|
if admin_contact.domain.discarded?
|
||||||
|
skipped_domains << admin_contact.domain.name
|
||||||
|
next
|
||||||
|
end
|
||||||
|
begin
|
||||||
|
admin_contact.contact = new_contact
|
||||||
|
admin_contact.save!
|
||||||
|
affected_domains << admin_contact.domain.name
|
||||||
|
rescue ActiveRecord::RecordNotUnique
|
||||||
|
skipped_domains << admin_contact.domain.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
[affected_domains.sort, skipped_domains.sort]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,6 +20,12 @@ module Concerns::Contact::Identical
|
||||||
.where.not(id: id).take
|
.where.not(id: id).take
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def identical_to?(contact)
|
||||||
|
IDENTIFIABLE_ATTRIBUTES.all? do |attribute|
|
||||||
|
self.attributes[attribute] == contact.attributes[attribute]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def identifiable_hash
|
def identifiable_hash
|
||||||
|
|
|
@ -64,6 +64,7 @@ Rails.application.routes.draw do
|
||||||
get ':id/transfer_info', to: 'domains#transfer_info', constraints: { id: /.*/ }
|
get ':id/transfer_info', to: 'domains#transfer_info', constraints: { id: /.*/ }
|
||||||
post 'transfer', to: 'domains#transfer'
|
post 'transfer', to: 'domains#transfer'
|
||||||
patch 'contacts', to: 'domains/contacts#update'
|
patch 'contacts', to: 'domains/contacts#update'
|
||||||
|
patch 'admin_contacts', to: 'domains/admin_contacts#update'
|
||||||
post 'renew/bulk', to: 'domains/renews#bulk_renew'
|
post 'renew/bulk', to: 'domains/renews#bulk_renew'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,48 +5,48 @@ class APIDomainAdminContactsTest < ApplicationIntegrationTest
|
||||||
@admin_current = domains(:shop).admin_contacts.find_by(code: 'jane-001')
|
@admin_current = domains(:shop).admin_contacts.find_by(code: 'jane-001')
|
||||||
@admin_new = contacts(:william)
|
@admin_new = contacts(:william)
|
||||||
|
|
||||||
@admin_new.update(ident: @admin_current.ident,
|
@admin_new.update(ident: @admin_current.ident,
|
||||||
ident_type: @admin_current.ident_type,
|
ident_type: @admin_current.ident_type,
|
||||||
ident_country_code: @admin_current.ident_country_code)
|
ident_country_code: @admin_current.ident_country_code)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_replace_all_admin_contacts_when_ident_data_doesnt_match
|
def test_replace_all_admin_contacts_when_ident_data_doesnt_match
|
||||||
@admin_new.update(ident: '777' ,
|
@admin_new.update(ident: '777' ,
|
||||||
ident_type: 'priv',
|
ident_type: 'priv',
|
||||||
ident_country_code: 'LV')
|
ident_country_code: 'LV')
|
||||||
|
|
||||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current,
|
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||||
new_contact_id: @admin_new },
|
new_contact_id: @admin_new.code },
|
||||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
assert_response :bad_request
|
assert_response :bad_request
|
||||||
assert_equal ({ code: 2304, message: 'New admin contact must have same ident' }),
|
assert_equal ({ code: 2304, message: 'Admin contacts must be identical', data: {} }),
|
||||||
JSON.parse(response.body, symbolize_names: true)
|
JSON.parse(response.body, symbolize_names: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_replace_all_admin_contacts_of_the_current_registrar
|
def test_replace_all_admin_contacts_of_the_current_registrar
|
||||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current,
|
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||||
new_contact_id: @admin_new },
|
new_contact_id: @admin_new.code },
|
||||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
assert_nil domains(:shop).admin_contacts.find_by(code: @admin_current)
|
assert_nil domains(:shop).admin_contacts.find_by(code: @admin_current.code)
|
||||||
assert domains(:shop).admin_contacts.find_by(code: @admin_new)
|
assert domains(:shop).admin_contacts.find_by(code: @admin_new.code)
|
||||||
assert domains(:airport).admin_contacts.find_by(code: @admin_new)
|
assert domains(:airport).admin_contacts.find_by(code: @admin_new.code)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_skip_discarded_domains
|
def test_skip_discarded_domains
|
||||||
domains(:airport).update!(statuses: [DomainStatus::DELETE_CANDIDATE])
|
domains(:airport).update!(statuses: [DomainStatus::DELETE_CANDIDATE])
|
||||||
|
|
||||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current,
|
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||||
new_contact_id: @admin_new },
|
new_contact_id: @admin_new.code },
|
||||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
assert domains(:shop).admin_contacts.find_by(code: @admin_current)
|
assert domains(:shop).admin_contacts.find_by(code: @admin_current.code)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_return_affected_domains_in_alphabetical_order
|
def test_return_affected_domains_in_alphabetical_order
|
||||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current,
|
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||||
new_contact_id: @admin_new },
|
new_contact_id: @admin_new.code },
|
||||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
assert_response :ok
|
assert_response :ok
|
||||||
|
@ -59,8 +59,8 @@ class APIDomainAdminContactsTest < ApplicationIntegrationTest
|
||||||
domains(:shop).update!(statuses: [DomainStatus::DELETE_CANDIDATE])
|
domains(:shop).update!(statuses: [DomainStatus::DELETE_CANDIDATE])
|
||||||
domains(:airport).update!(statuses: [DomainStatus::DELETE_CANDIDATE])
|
domains(:airport).update!(statuses: [DomainStatus::DELETE_CANDIDATE])
|
||||||
|
|
||||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current,
|
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||||
new_contact_id: @admin_new },
|
new_contact_id: @admin_new.code },
|
||||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
assert_response :ok
|
assert_response :ok
|
||||||
|
@ -69,23 +69,23 @@ class APIDomainAdminContactsTest < ApplicationIntegrationTest
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_keep_other_admin_contacts_intact
|
def test_keep_other_admin_contacts_intact
|
||||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current,
|
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||||
new_contact_id: @admin_new },
|
new_contact_id: @admin_new.code },
|
||||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
assert domains(:airport).admin_contacts.find_by(code: 'john-001')
|
assert domains(:airport).admin_contacts.find_by(code: 'john-001')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_keep_tech_contacts_intact
|
def test_keep_tech_contacts_intact
|
||||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current,
|
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||||
new_contact_id: @admin_new },
|
new_contact_id: @admin_new.code },
|
||||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
assert domains(:airport).tech_contacts.find_by(code: 'william-001')
|
assert domains(:airport).tech_contacts.find_by(code: 'william-001')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_restrict_contacts_to_the_current_registrar
|
def test_restrict_contacts_to_the_current_registrar
|
||||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current,
|
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||||
new_contact_id: 'william-002' },
|
new_contact_id: 'william-002' },
|
||||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ class APIDomainAdminContactsTest < ApplicationIntegrationTest
|
||||||
|
|
||||||
def test_non_existent_current_contact
|
def test_non_existent_current_contact
|
||||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: 'non-existent',
|
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: 'non-existent',
|
||||||
new_contact_id: @admin_new},
|
new_contact_id: @admin_new.code},
|
||||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
assert_response :not_found
|
assert_response :not_found
|
||||||
assert_equal ({ code: 2303, message: 'Object does not exist' }),
|
assert_equal ({ code: 2303, message: 'Object does not exist' }),
|
||||||
|
@ -104,7 +104,7 @@ class APIDomainAdminContactsTest < ApplicationIntegrationTest
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_non_existent_new_contact
|
def test_non_existent_new_contact
|
||||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current,
|
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||||
new_contact_id: 'non-existent' },
|
new_contact_id: 'non-existent' },
|
||||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
assert_response :not_found
|
assert_response :not_found
|
||||||
|
@ -113,7 +113,7 @@ class APIDomainAdminContactsTest < ApplicationIntegrationTest
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_disallow_invalid_new_contact
|
def test_disallow_invalid_new_contact
|
||||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current,
|
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||||
new_contact_id: 'invalid' },
|
new_contact_id: 'invalid' },
|
||||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
assert_response :bad_request
|
assert_response :bad_request
|
||||||
|
@ -122,8 +122,8 @@ class APIDomainAdminContactsTest < ApplicationIntegrationTest
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_disallow_self_replacement
|
def test_disallow_self_replacement
|
||||||
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current,
|
patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code,
|
||||||
new_contact_id: @admin_current },
|
new_contact_id: @admin_current.code },
|
||||||
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
|
||||||
assert_response :bad_request
|
assert_response :bad_request
|
||||||
assert_equal ({ code: 2304, message: 'New contact must be different from current', data: {} }),
|
assert_equal ({ code: 2304, message: 'New contact must be different from current', data: {} }),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue