diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9afedbf17..6470a9471 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,19 @@
+26.02.2021
+* Domain delete is not affected by updateProhibited [#1844](https://github.com/internetee/registry/issues/1844)
+* Registrant API fix for handling eidas personal identificators [#1864](https://github.com/internetee/registry/pull/1864)
+
+23.02.2021
+* UpdateProhibited status affects bulk actions in REPP [#1818](https://github.com/internetee/registry/issues/1818)
+* Registrant api domain request now excludes tech only domains by default [#1836](https://github.com/internetee/registry/pull/1836)
+
+22.02.2021
+* serverDeleteProhibited prohibts delete action [#1849](https://github.com/internetee/registry/issues/1849)
+
+19.02.2021
+* Update prohibited staatus is kept after renew [#1843](https://github.com/internetee/registry/issues/1843)
+* Fixed clientHold and serverManualInzone status conflict issue [#1845](https://github.com/internetee/registry/issues/1845)
+* Replacing registrant object with another that has the same ident data set does not require registrant verification [#1852](https://github.com/internetee/registry/issues/1852)
+
11.02.2021
* Poll messages on locking and unlocking a domain [#1828](https://github.com/internetee/registry/issues/1828)
* Registrar's prefix is now checked and added to contact id for info and check requests [#1832](https://github.com/internetee/registry/issues/1832)
diff --git a/app/controllers/api/v1/registrant/auth_controller.rb b/app/controllers/api/v1/registrant/auth_controller.rb
index 03dfa45f3..728ef696d 100644
--- a/app/controllers/api/v1/registrant/auth_controller.rb
+++ b/app/controllers/api/v1/registrant/auth_controller.rb
@@ -19,6 +19,9 @@ module Api
token = create_token(user)
if token
+ msg = "Bearer for #{eid_params[:first_name]} #{eid_params[:last_name]} " \
+ "(#{eid_params[:ident]}) - '#{token[:access_token]}'"
+ ToStdout.msg(msg) unless Rails.env.production?
render json: token
else
render json: { errors: [{ base: ['Cannot create generate session token'] }] }
@@ -37,7 +40,7 @@ module Api
obj.require(key)
end
- params.permit(required_params)
+ params.permit(required_params + [:country_code])
end
def create_token(user)
diff --git a/app/controllers/api/v1/registrant/domains_controller.rb b/app/controllers/api/v1/registrant/domains_controller.rb
index 73b534598..94d2c865a 100644
--- a/app/controllers/api/v1/registrant/domains_controller.rb
+++ b/app/controllers/api/v1/registrant/domains_controller.rb
@@ -4,6 +4,8 @@ module Api
module V1
module Registrant
class DomainsController < ::Api::V1::Registrant::BaseController
+ before_action :set_tech_flag, only: [:show]
+
def index
limit = params[:limit] || 200
offset = params[:offset] || 0
@@ -25,7 +27,8 @@ module Api
serializer.to_json
end
- render json: { count: domains.count, domains: serialized_domains }
+ render json: { total: current_user_domains_total_count, count: domains.count,
+ domains: serialized_domains }
end
def show
@@ -41,10 +44,22 @@ module Api
private
- def current_user_domains
- current_registrant_user.domains
+ def set_tech_flag
+ # current_user_domains scope depends on tech flag
+ # However, if it's not present, tech contact can not see specific domain entry at all.
+ params.merge!(tech: 'true')
+ end
+
+ def current_user_domains_total_count
+ current_registrant_user.domains.count
rescue CompanyRegister::NotAvailableError
- current_registrant_user.direct_domains
+ current_registrant_user.direct_domains.count
+ end
+
+ def current_user_domains
+ current_registrant_user.domains(admin: params[:tech] != 'true')
+ rescue CompanyRegister::NotAvailableError
+ current_registrant_user.direct_domains(admin: params[:tech] != 'true')
end
end
end
diff --git a/app/models/actions/contact_delete.rb b/app/models/actions/contact_delete.rb
index 59032d566..60d3252c4 100644
--- a/app/models/actions/contact_delete.rb
+++ b/app/models/actions/contact_delete.rb
@@ -19,6 +19,11 @@ module Actions
return
end
+ if contact.delete_prohibited?
+ contact.errors.add(:statuses, :delete_prohibited)
+ return
+ end
+
commit
end
diff --git a/app/models/concerns/domain/deletable.rb b/app/models/concerns/domain/deletable.rb
index 81518c739..3c63cf96d 100644
--- a/app/models/concerns/domain/deletable.rb
+++ b/app/models/concerns/domain/deletable.rb
@@ -1,6 +1,12 @@
module Concerns::Domain::Deletable
extend ActiveSupport::Concern
+ DELETE_STATUSES = [
+ DomainStatus::PENDING_DELETE_CONFIRMATION,
+ DomainStatus::PENDING_DELETE,
+ DomainStatus::FORCE_DELETE,
+ ].freeze
+
private
def delete_later
diff --git a/app/models/concerns/domain/force_delete.rb b/app/models/concerns/domain/force_delete.rb
index 87e9a957b..5f09dd9fb 100644
--- a/app/models/concerns/domain/force_delete.rb
+++ b/app/models/concerns/domain/force_delete.rb
@@ -11,6 +11,11 @@ module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength
lambda {
where("(force_delete_data->>'contact_notification_sent_date') is null")
}
+
+ HOLD_STATUSES = [
+ DomainStatus::SERVER_HOLD,
+ DomainStatus::CLIENT_HOLD,
+ ].freeze
end
class_methods do
@@ -19,6 +24,10 @@ module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength
end
end
+ def hold_status?
+ HOLD_STATUSES.any? { |status| statuses.include? status }
+ end
+
def notification_template(explicit: nil)
reason = explicit&.downcase
return reason if %w[invalid_email invalid_phone].include?(reason)
diff --git a/app/models/concerns/domain/transferable.rb b/app/models/concerns/domain/transferable.rb
index 5400e9409..649600217 100644
--- a/app/models/concerns/domain/transferable.rb
+++ b/app/models/concerns/domain/transferable.rb
@@ -31,7 +31,9 @@ module Concerns::Domain::Transferable
DomainStatus::PENDING_TRANSFER,
DomainStatus::FORCE_DELETE,
DomainStatus::SERVER_TRANSFER_PROHIBITED,
- DomainStatus::CLIENT_TRANSFER_PROHIBITED
+ DomainStatus::CLIENT_TRANSFER_PROHIBITED,
+ DomainStatus::SERVER_UPDATE_PROHIBITED,
+ DomainStatus::CLIENT_UPDATE_PROHIBITED,
]).empty?
end
diff --git a/app/models/domain.rb b/app/models/domain.rb
index 53f0fa5b6..f5fed455d 100644
--- a/app/models/domain.rb
+++ b/app/models/domain.rb
@@ -107,13 +107,13 @@ class Domain < ApplicationRecord
validate :status_is_consistant
def status_is_consistant
- has_error = (statuses.include?(DomainStatus::SERVER_HOLD) && statuses.include?(DomainStatus::SERVER_MANUAL_INZONE))
- unless has_error
- if (statuses & [DomainStatus::PENDING_DELETE_CONFIRMATION, DomainStatus::PENDING_DELETE, DomainStatus::FORCE_DELETE]).any?
- has_error = statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED
- end
+ has_error = (hold_status? && statuses.include?(DomainStatus::SERVER_MANUAL_INZONE))
+ unless has_error
+ if (statuses & DELETE_STATUSES).any?
+ has_error = statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED
end
- errors.add(:domains, I18n.t(:object_status_prohibits_operation)) if has_error
+ end
+ errors.add(:domains, I18n.t(:object_status_prohibits_operation)) if has_error
end
attr_accessor :is_admin
@@ -198,6 +198,23 @@ class Domain < ApplicationRecord
Setting.nameserver_required
end
+ def registrant_user_admin_registrant_domains(registrant_user)
+ companies = Contact.registrant_user_company_contacts(registrant_user)
+ from(
+ "(#{registrant_user_administered_domains(registrant_user).to_sql} UNION " \
+ "#{registrant_user_company_registrant(companies).to_sql} UNION " \
+ "#{registrant_user_domains_company(companies, except_tech: true).to_sql}) AS domains"
+ )
+ end
+
+ def registrant_user_direct_admin_registrant_domains(registrant_user)
+ from(
+ "(#{registrant_user_direct_domains_by_registrant(registrant_user).to_sql} UNION " \
+ "#{registrant_user_direct_domains_by_contact(registrant_user,
+ except_tech: true).to_sql}) AS domains"
+ )
+ end
+
def registrant_user_domains(registrant_user)
from(
"(#{registrant_user_domains_by_registrant(registrant_user).to_sql} UNION " \
@@ -247,16 +264,20 @@ class Domain < ApplicationRecord
where(registrant: registrant_user.direct_contacts)
end
- def registrant_user_direct_domains_by_contact(registrant_user)
- joins(:domain_contacts).where(domain_contacts: { contact_id: registrant_user.direct_contacts })
+ def registrant_user_direct_domains_by_contact(registrant_user, except_tech: false)
+ request = { contact_id: registrant_user.direct_contacts }
+ request[:type] = [AdminDomainContact.name] if except_tech
+ joins(:domain_contacts).where(domain_contacts: request)
end
def registrant_user_company_registrant(companies)
where(registrant: companies)
end
- def registrant_user_domains_company(companies)
- joins(:domain_contacts).where(domain_contacts: { contact: companies })
+ def registrant_user_domains_company(companies, except_tech: false)
+ request = { contact: companies }
+ request[:type] = [AdminDomainContact.name] if except_tech
+ joins(:domain_contacts).where(domain_contacts: request)
end
end
diff --git a/app/models/domain_status.rb b/app/models/domain_status.rb
index bf0ae2a51..30161c076 100644
--- a/app/models/domain_status.rb
+++ b/app/models/domain_status.rb
@@ -109,14 +109,12 @@ class DomainStatus < ApplicationRecord
DELETE_PROHIBIT_STATES = [
DomainStatus::CLIENT_DELETE_PROHIBITED,
DomainStatus::SERVER_DELETE_PROHIBITED,
- DomainStatus::CLIENT_UPDATE_PROHIBITED,
- DomainStatus::SERVER_UPDATE_PROHIBITED,
DomainStatus::PENDING_CREATE,
DomainStatus::PENDING_RENEW,
DomainStatus::PENDING_TRANSFER,
DomainStatus::PENDING_UPDATE,
DomainStatus::PENDING_DELETE
- ]
+ ].freeze
def epp_code_map
{
diff --git a/app/models/epp/contact.rb b/app/models/epp/contact.rb
index 0c0ed3d5f..4cd876d5f 100644
--- a/app/models/epp/contact.rb
+++ b/app/models/epp/contact.rb
@@ -82,8 +82,11 @@ class Epp::Contact < Contact
'2302' => [ # Object exists
[:code, :epp_id_taken]
],
+ '2304' => [ # Status prohibits operation
+ [:statuses, :delete_prohibited],
+ ],
'2305' => [ # Association exists
- [:domains, :exist]
+ [:domains, :exist],
]
}
end
diff --git a/app/models/epp/domain.rb b/app/models/epp/domain.rb
index f280eb160..f3da8d533 100644
--- a/app/models/epp/domain.rb
+++ b/app/models/epp/domain.rb
@@ -465,7 +465,7 @@ class Epp::Domain < Domain
def update(frame, current_user, verify = true)
return super if frame.blank?
- if discarded?
+ if discarded? || statuses_blocks_update?
add_epp_error('2304', nil, nil, 'Object status prohibits operation')
return
end
@@ -495,7 +495,7 @@ class Epp::Domain < Domain
registrant_verification_needed = false
# registrant block may not be present, so we need this to rule out false positives
if frame.css('registrant').text.present?
- registrant_verification_needed = (registrant.code != frame.css('registrant').text)
+ registrant_verification_needed = verification_needed?(code: frame.css('registrant').text)
end
if registrant_verification_needed && disputed?
@@ -797,4 +797,13 @@ class Epp::Domain < Domain
result
end
end
+
+ private
+
+ def verification_needed?(code:)
+ new_registrant = Registrant.find_by(code: code)
+ return false if new_registrant.try(:identical_to?, registrant)
+
+ registrant.code != code
+ end
end
diff --git a/app/models/registrant_user.rb b/app/models/registrant_user.rb
index aa41ccff8..f7e85c5af 100644
--- a/app/models/registrant_user.rb
+++ b/app/models/registrant_user.rb
@@ -9,7 +9,7 @@ class RegistrantUser < User
delegate :can?, :cannot?, to: :ability
def ident
- registrant_ident.to_s.split('-').last
+ registrant_ident.to_s[3..]
end
def country
@@ -18,6 +18,8 @@ class RegistrantUser < User
end
def companies(company_register = CompanyRegister::Client.new)
+ return [] if ident.include?('-')
+
company_register.representation_rights(citizen_personal_code: ident,
citizen_country_code: country.alpha3)
end
@@ -30,11 +32,15 @@ class RegistrantUser < User
Contact.registrant_user_direct_contacts(self)
end
- def domains
+ def domains(admin: false)
+ return Domain.registrant_user_admin_registrant_domains(self) if admin
+
Domain.registrant_user_domains(self)
end
- def direct_domains
+ def direct_domains(admin: false)
+ return Domain.registrant_user_direct_admin_registrant_domains(self) if admin
+
Domain.registrant_user_direct_domains(self)
end
@@ -72,7 +78,7 @@ class RegistrantUser < User
return false unless user_data[:last_name]
user_data[:country_code] ||= 'EE'
- %i[ident country_code].each { |f| user_data[f].upcase! if user_data[f].is_a?(String) }
+ user_data[:country_code].upcase! if user_data[:country_code].is_a?(String)
find_or_create_by_user_data(user_data)
end
diff --git a/app/models/registrar.rb b/app/models/registrar.rb
index 168dfdca7..652864fe5 100644
--- a/app/models/registrar.rb
+++ b/app/models/registrar.rb
@@ -153,7 +153,7 @@ class Registrar < ApplicationRecord
puny = origin.domain.name_puny
next unless domains.include?(idn) || domains.include?(puny) || domains.empty?
- if origin.domain.nameservers.where(hostname: new_attributes[:hostname]).any?
+ if domain_not_updatable?(hostname: new_attributes[:hostname], domain: origin.domain)
failed_list << idn
next
end
@@ -202,6 +202,10 @@ class Registrar < ApplicationRecord
private
+ def domain_not_updatable?(hostname:, domain:)
+ domain.nameservers.where(hostname: hostname).any? || domain.bulk_update_prohibited?
+ end
+
def set_defaults
self.language = Setting.default_language unless language
end
diff --git a/config/locales/contacts.en.yml b/config/locales/contacts.en.yml
index 906bde193..4b4d099d7 100644
--- a/config/locales/contacts.en.yml
+++ b/config/locales/contacts.en.yml
@@ -25,8 +25,10 @@ en:
email_regex_check_error: Invalid format
domains:
exist: 'Object association prohibits operation'
+ delete_prohibited: Contact delete prohibited by status
statuses:
not_uniq: 'not uniq'
+ delete_prohibited: Contact delete prohibited by status
country_code:
invalid: Country code is not valid, should be in ISO_3166-1 alpha 2 format (%{value})
disclosed_attributes:
diff --git a/lib/serializers/registrant_api/domain.rb b/lib/serializers/registrant_api/domain.rb
index 64913a7fb..ed6eb2b9c 100644
--- a/lib/serializers/registrant_api/domain.rb
+++ b/lib/serializers/registrant_api/domain.rb
@@ -25,6 +25,7 @@ module Serializers
registrant: {
name: domain.registrant.name,
id: domain.registrant.uuid,
+ org: domain.registrant.org?,
},
tech_contacts: contacts(:tech),
admin_contacts: contacts(:admin),
@@ -60,7 +61,7 @@ module Serializers
registrar: { name: domain.registrar.name, website: domain.registrar.website },
registrant: { name: domain.registrant.name, id: domain.registrant.uuid,
phone: domain.registrant.phone, email: domain.registrant.email,
- ident: domain.registrant.ident }
+ ident: domain.registrant.ident, org: domain.registrant.org? }
}
end
diff --git a/test/integration/api/domain_transfers_test.rb b/test/integration/api/domain_transfers_test.rb
index 3e9c10100..3ed5b0fc6 100644
--- a/test/integration/api/domain_transfers_test.rb
+++ b/test/integration/api/domain_transfers_test.rb
@@ -63,6 +63,23 @@ class APIDomainTransfersTest < ApplicationIntegrationTest
assert_equal 1, @new_registrar.contacts.where(name: 'William').size
end
+ def test_bulk_transfer_if_domain_has_update_prohibited_status
+ domains(:shop).update!(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED])
+
+ post '/repp/v1/domains/transfer', params: request_params, as: :json,
+ headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
+
+ assert_response :ok
+ assert_equal ({ code: 1000,
+ message: 'Command completed successfully',
+ data: { success: [],
+ failed: [{ type: "domain_transfer",
+ domain_name: "shop.test",
+ errors: [{:code=>"2304", :msg=>"Object status prohibits operation"}] }],
+ }}),
+ JSON.parse(response.body, symbolize_names: true)
+ end
+
private
def request_params
diff --git a/test/integration/api/nameservers/put_test.rb b/test/integration/api/nameservers/put_test.rb
index 77b01a9b1..a55014709 100644
--- a/test/integration/api/nameservers/put_test.rb
+++ b/test/integration/api/nameservers/put_test.rb
@@ -104,6 +104,25 @@ class APINameserversPutTest < ApplicationIntegrationTest
JSON.parse(response.body, symbolize_names: true)
end
+ def test_bulk_namesaervers_if_domain_update_prohibited
+ domains(:shop).update!(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED])
+
+ params = { data: { type: 'nameserver', id: domains(:shop).nameservers.hostnames[0],
+ attributes: { hostname: 'ns55.bestnames.test' } } }
+ put '/repp/v1/registrar/nameservers', params: params, as: :json,
+ headers: { 'HTTP_AUTHORIZATION' => http_auth_key }
+
+ assert_response :ok
+ assert_equal ({ code: 1000,
+ message: 'Command completed successfully',
+ data: { type: "nameserver",
+ id: "ns55.bestnames.test",
+ attributes: {hostname: "ns55.bestnames.test"},
+ affected_domains: ["airport.test"],
+ skipped_domains: ["shop.test"]}}),
+ JSON.parse(response.body, symbolize_names: true)
+ end
+
def test_unauthenticated
put '/repp/v1/registrar/nameservers'
assert_response 401
diff --git a/test/integration/api/registrant/registrant_api_domains_test.rb b/test/integration/api/registrant/registrant_api_domains_test.rb
index 61d635e5f..4cfa6bd55 100644
--- a/test/integration/api/registrant/registrant_api_domains_test.rb
+++ b/test/integration/api/registrant/registrant_api_domains_test.rb
@@ -5,9 +5,10 @@ class RegistrantApiDomainsTest < ApplicationIntegrationTest
def setup
super
- @domain = domains(:hospital)
+ @domain = domains(:airport)
@registrant = @domain.registrant
@user = users(:registrant)
+ domains(:metro).tech_domain_contacts.update(contact_id: @registrant.id)
@auth_headers = { 'HTTP_AUTHORIZATION' => auth_token }
end
@@ -19,7 +20,7 @@ class RegistrantApiDomainsTest < ApplicationIntegrationTest
assert_equal('hospital.test', domain[:name])
assert_equal('5edda1a5-3548-41ee-8b65-6d60daf85a37', domain[:id])
- assert_equal({name: 'John', id: 'eb2f2766-b44c-4e14-9f16-32ab1a7cb957'}, domain[:registrant])
+ assert_equal({name: 'John', id: 'eb2f2766-b44c-4e14-9f16-32ab1a7cb957', org: false}, domain[:registrant])
assert_equal([{name: 'John',
id: 'eb2f2766-b44c-4e14-9f16-32ab1a7cb957',
email: 'john@inbox.test'}],
@@ -57,6 +58,46 @@ class RegistrantApiDomainsTest < ApplicationIntegrationTest
assert(array_of_domain_registrars.include?({name: 'Good Names', website: nil}))
end
+ def test_return_domain_list_with_registrants_and_admins
+ domains(:hospital).admin_domain_contacts.update(contact_id: contacts(:william).id)
+ domains(:hospital).update(registrant: contacts(:william).becomes(Registrant))
+
+ get '/api/v1/registrant/domains', headers: @auth_headers, params: { 'offset' => 0 }
+ assert_equal(200, response.status)
+
+ response_json = JSON.parse(response.body, symbolize_names: true)
+ response_json[:domains].each do |x|
+ if x[:registrant][:org] == false
+ x[:tech_contacts].each do |s|
+ assert_not s[:name].include?(@registrant.name)
+ end
+ end
+ end
+ end
+
+ def test_return_domain_list_with_registrants_and_admins_tech
+ get '/api/v1/registrant/domains', headers: @auth_headers, params: { 'offset' => 0, 'tech' => true }
+ assert_equal(200, response.status)
+
+ response_json = JSON.parse(response.body, symbolize_names: true)
+ response_json[:domains].each do |x|
+ if x[:name] == 'metro.test'
+ x[:tech_contacts].each do |s|
+ assert s[:name].include?(@registrant.name)
+ end
+ end
+ end
+ end
+
+ def test_domains_total_if_an_incomplete_list_is_returned
+ get '/api/v1/registrant/domains', headers: @auth_headers, params: { 'offset' => 0 }
+ assert_equal(200, response.status)
+
+ response_json = JSON.parse(response.body, symbolize_names: true)
+ assert_equal response_json[:domains].length, response_json[:count]
+ assert_equal response_json[:total], 5
+ end
+
def test_root_accepts_limit_and_offset_parameters
get '/api/v1/registrant/domains', params: { 'limit' => 2, 'offset' => 0 },
headers: @auth_headers
diff --git a/test/integration/api/registrant/registrant_api_registry_locks_test.rb b/test/integration/api/registrant/registrant_api_registry_locks_test.rb
index fb6d13aca..d024bb6c1 100644
--- a/test/integration/api/registrant/registrant_api_registry_locks_test.rb
+++ b/test/integration/api/registrant/registrant_api_registry_locks_test.rb
@@ -130,7 +130,7 @@ class RegistrantApiRegistryLocksTest < ApplicationIntegrationTest
response_json = JSON.parse(response.body, symbolize_names: true)
assert_equal({ name: 'Best Names', website: 'https://bestnames.test' }, response_json[:registrar])
- assert_equal({name: 'John', id: 'eb2f2766-b44c-4e14-9f16-32ab1a7cb957'}, response_json[:registrant])
+ assert_equal({name: 'John', id: 'eb2f2766-b44c-4e14-9f16-32ab1a7cb957', org: false}, response_json[:registrant])
assert_equal([{name: 'Jane',
id: '9db3de62-2414-4487-bee2-d5c155567768',
email: 'jane@mail.test'
diff --git a/test/integration/epp/contact/delete/base_test.rb b/test/integration/epp/contact/delete/base_test.rb
index 26ba63897..e86bea9dd 100644
--- a/test/integration/epp/contact/delete/base_test.rb
+++ b/test/integration/epp/contact/delete/base_test.rb
@@ -27,6 +27,60 @@ class EppContactDeleteBaseTest < EppTestCase
assert_epp_response :completed_successfully
end
+ def test_delete_contact_with_server_delete_prohibited
+ contact = deletable_contact
+ contact.update(statuses: Contact::SERVER_DELETE_PROHIBITED)
+ assert contact.statuses.include? Contact::SERVER_DELETE_PROHIBITED
+
+ contact.update_columns(code: contact.code.upcase)
+
+ request_xml = <<-XML
+
+
+
+
+
+ #{contact.code.upcase}
+
+
+
+
+ XML
+
+ post epp_delete_path, params: { frame: request_xml },
+ headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
+
+ assert Contact.exists?(id: contact.id)
+ assert_epp_response :object_status_prohibits_operation
+ end
+
+ def test_delete_contact_with_client_delete_prohibited
+ contact = deletable_contact
+ contact.update(statuses: Contact::CLIENT_DELETE_PROHIBITED)
+ assert contact.statuses.include? Contact::CLIENT_DELETE_PROHIBITED
+
+ contact.update_columns(code: contact.code.upcase)
+
+ request_xml = <<-XML
+
+
+
+
+
+ #{contact.code.upcase}
+
+
+
+
+ XML
+
+ post epp_delete_path, params: { frame: request_xml },
+ headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
+
+ assert Contact.exists?(id: contact.id)
+ assert_epp_response :object_status_prohibits_operation
+ end
+
def test_undeletable_cannot_be_deleted
contact = contacts(:john)
assert_not contact.deletable?
@@ -61,4 +115,4 @@ class EppContactDeleteBaseTest < EppTestCase
DomainContact.delete_all
contacts(:john)
end
-end
\ No newline at end of file
+end
diff --git a/test/integration/epp/domain/delete/base_test.rb b/test/integration/epp/domain/delete/base_test.rb
index 56a3cc31e..d32a89f63 100644
--- a/test/integration/epp/domain/delete/base_test.rb
+++ b/test/integration/epp/domain/delete/base_test.rb
@@ -133,6 +133,40 @@ class EppDomainDeleteBaseTest < EppTestCase
assert_epp_response :completed_successfully
end
+ def test_deletes_on_update_prohibited
+ assert_equal 'shop.test', @domain.name
+ @domain.update(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED])
+ Setting.request_confirmation_on_domain_deletion_enabled = false
+
+ request_xml = <<-XML
+
+
+
+
+
+ shop.test
+
+
+
+
+ #{'test' * 2000}
+
+
+
+
+ XML
+
+ perform_enqueued_jobs do
+ post epp_delete_path, params: { frame: request_xml }, headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
+ end
+ @domain.reload
+
+ assert_not @domain.registrant_verification_asked?
+ assert_not @domain.pending_delete_confirmation?
+ assert_no_emails
+ assert_epp_response :completed_successfully
+ end
+
def test_skips_registrant_confirmation_when_required_but_already_verified_by_registrar
assert_equal 'shop.test', @domain.name
Setting.request_confirmation_on_domain_deletion_enabled = true
diff --git a/test/integration/epp/domain/update/base_test.rb b/test/integration/epp/domain/update/base_test.rb
index 14e806fca..53531e8b5 100644
--- a/test/integration/epp/domain/update/base_test.rb
+++ b/test/integration/epp/domain/update/base_test.rb
@@ -62,6 +62,27 @@ class EppDomainUpdateBaseTest < EppTestCase
assert_epp_response :object_status_prohibits_operation
end
+ def test_prohibited_domain_cannot_be_updated
+ @domain.update!(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED])
+
+ request_xml = <<-XML
+
+
+
+
+
+ shop.test
+
+
+
+
+ XML
+
+ post epp_update_path, params: { frame: request_xml },
+ headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
+ assert_epp_response :object_status_prohibits_operation
+ end
+
def test_does_not_return_server_delete_prohibited_status_when_pending_update_status_is_set
@domain.update!(statuses: [DomainStatus::SERVER_DELETE_PROHIBITED,
DomainStatus::PENDING_UPDATE])
@@ -123,6 +144,46 @@ class EppDomainUpdateBaseTest < EppTestCase
assert_verification_and_notification_emails
end
+ def test_domain_should_doesnt_have_pending_update_when_updated_registrant_with_same_idents_data
+ assert_not @domain.statuses.include? "pendingUpdate"
+
+ old_registrant = @domain.registrant
+ new_registrant = contacts(:william).becomes(Registrant)
+
+ new_registrant.update(ident: old_registrant.ident)
+ new_registrant.update(ident_country_code: old_registrant.ident_country_code)
+ new_registrant.update(ident_type: old_registrant.ident_type)
+
+ request_xml = <<-XML
+
+
+
+
+
+ #{@domain.name}
+
+ #{new_registrant.code}
+
+
+
+
+
+ #{'test' * 2000}
+
+
+
+
+ XML
+
+ post epp_update_path, params: { frame: request_xml },
+ headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
+ @domain.reload
+ assert_epp_response :completed_successfully
+
+ assert_equal @domain.registrant, new_registrant
+ assert_not @domain.statuses.include? "pendingUpdate"
+ end
+
def test_requires_verification_from_current_registrant_when_not_yet_verified_by_registrar
Setting.request_confirmation_on_registrant_change_enabled = true
new_registrant = contacts(:william)
diff --git a/test/integration/repp/v1/registrar/nameservers_test.rb b/test/integration/repp/v1/registrar/nameservers_test.rb
index f01769dfb..e2c6f890b 100644
--- a/test/integration/repp/v1/registrar/nameservers_test.rb
+++ b/test/integration/repp/v1/registrar/nameservers_test.rb
@@ -34,6 +34,33 @@ class ReppV1RegistrarNameserversTest < ActionDispatch::IntegrationTest
assert json[:data][:affected_domains].include? 'shop.test'
end
+ def test_fails_to_update_if_prohibited
+ domain = domains(:shop)
+ domain.update(statuses: [DomainStatus::CLIENT_UPDATE_PROHIBITED])
+ nameserver = nameservers(:shop_ns1)
+ payload = {
+ "data": {
+ "id": nameserver.hostname,
+ "type": "nameserver",
+ "attributes": {
+ "hostname": "#{nameserver.hostname}.test",
+ "ipv4": ["1.1.1.1"]
+ }
+ }
+ }
+
+ put '/repp/v1/registrar/nameservers', headers: @auth_headers, params: payload
+ json = JSON.parse(response.body, symbolize_names: true)
+
+ assert_response :ok
+ assert_equal 1000, json[:code]
+ assert_equal 'Command completed successfully', json[:message]
+ assert_equal({ hostname: "#{nameserver.hostname}.test", ipv4: ["1.1.1.1"] }, json[:data][:attributes])
+ assert_equal({ hostname: "#{nameserver.hostname}.test", ipv4: ["1.1.1.1"] }, json[:data][:attributes])
+ assert json[:data][:affected_domains].include? 'airport.test'
+ assert json[:data][:skipped_domains].include? 'shop.test'
+ end
+
def test_nameserver_with_hostname_must_exist
payload = {
"data": {
diff --git a/test/lib/serializers/registrant_api/domain_test.rb b/test/lib/serializers/registrant_api/domain_test.rb
index f2623741f..d30a50ea3 100644
--- a/test/lib/serializers/registrant_api/domain_test.rb
+++ b/test/lib/serializers/registrant_api/domain_test.rb
@@ -30,8 +30,8 @@ class SerializersRegistrantApiDomainTest < ActiveSupport::TestCase
assert_equal({name: 'Best Names', website: 'https://bestnames.test' }, @json[:registrar])
end
- def test_returns_registrant_name_and_uuid
- assert_equal({name: 'John', id: 'eb2f2766-b44c-4e14-9f16-32ab1a7cb957'},
+ def test_returns_registrant_name_uuid_and_org
+ assert_equal({name: 'John', id: 'eb2f2766-b44c-4e14-9f16-32ab1a7cb957', org: false},
@json[:registrant])
end
diff --git a/test/models/domain/force_delete_test.rb b/test/models/domain/force_delete_test.rb
index 2bb1b5b8f..19338f495 100644
--- a/test/models/domain/force_delete_test.rb
+++ b/test/models/domain/force_delete_test.rb
@@ -234,6 +234,19 @@ class ForceDeleteTest < ActionMailer::TestCase
assert_includes(@domain.statuses, asserted_status)
end
+ def test_client_hold_prohibits_manual_inzone
+ @domain.update(valid_to: Time.zone.parse('2012-08-05'))
+ @domain.update(template_name: 'legal_person')
+ travel_to Time.zone.parse('2010-07-05')
+ @domain.schedule_force_delete(type: :soft)
+ travel_to Time.zone.parse('2010-08-21')
+ Domains::ClientHold::SetClientHold.run!
+ @domain.reload
+
+ @domain.statuses << DomainStatus::SERVER_MANUAL_INZONE
+ assert_not @domain.valid?
+ end
+
def test_force_delete_soft_year_ahead_not_sets_client_hold_before_threshold
asserted_status = DomainStatus::CLIENT_HOLD