Merge branch 'master' into 1795-validation-contacts-name

This commit is contained in:
Dinar Safiulin 2021-07-23 10:41:02 +03:00 committed by GitHub
commit aaedc31457
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 467 additions and 56 deletions

View file

@ -1,3 +1,8 @@
08.07.2021
* improved contact name validation [#1795](https://github.com/internetee/registry/issues/1795)
* orphaned poll messages are automatically dequed [#2026](https://github.com/internetee/registry/issues/2026)
* fixed registrant change with force delete set [#2077](https://github.com/internetee/registry/issues/2077)
06.07.2021 06.07.2021
* admin dropdown filter ui fix [#2065](https://github.com/internetee/registry/issues/2065) * admin dropdown filter ui fix [#2065](https://github.com/internetee/registry/issues/2065)
* Bump truemail to 2.4.4 [#2071](https://github.com/internetee/registry/pull/2071) * Bump truemail to 2.4.4 [#2071](https://github.com/internetee/registry/pull/2071)

View file

@ -115,7 +115,7 @@ GEM
erubi (~> 1.4) erubi (~> 1.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0)
active_interaction (4.0.4) active_interaction (4.0.5)
activemodel (>= 5, < 7) activemodel (>= 5, < 7)
activesupport (>= 5, < 7) activesupport (>= 5, < 7)
activejob (6.1.4) activejob (6.1.4)
@ -139,7 +139,7 @@ GEM
minitest (>= 5.1) minitest (>= 5.1)
tzinfo (~> 2.0) tzinfo (~> 2.0)
zeitwerk (~> 2.3) zeitwerk (~> 2.3)
addressable (2.7.0) addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0) public_suffix (>= 2.0.2, < 5.0)
aes_key_wrap (1.1.0) aes_key_wrap (1.1.0)
airbrake (11.0.3) airbrake (11.0.3)
@ -195,7 +195,7 @@ GEM
coffee-script-source (1.12.2) coffee-script-source (1.12.2)
concurrent-ruby (1.1.9) concurrent-ruby (1.1.9)
connection_pool (2.2.5) connection_pool (2.2.5)
countries (4.0.0) countries (4.0.1)
i18n_data (~> 0.13.0) i18n_data (~> 0.13.0)
sixarm_ruby_unaccent (~> 1.1) sixarm_ruby_unaccent (~> 1.1)
crack (0.4.5) crack (0.4.5)
@ -205,7 +205,7 @@ GEM
daemons-rails (1.2.1) daemons-rails (1.2.1)
daemons daemons
multi_json (~> 1.0) multi_json (~> 1.0)
data_migrate (7.0.1) data_migrate (7.0.2)
activerecord (>= 5.0) activerecord (>= 5.0)
railties (>= 5.0) railties (>= 5.0)
database_cleaner (2.0.1) database_cleaner (2.0.1)
@ -387,7 +387,7 @@ GEM
method_source method_source
rake (>= 0.13) rake (>= 0.13)
thor (~> 1.0) thor (~> 1.0)
rake (13.0.3) rake (13.0.6)
ransack (2.4.2) ransack (2.4.2)
activerecord (>= 5.2.4) activerecord (>= 5.2.4)
activesupport (>= 5.2.4) activesupport (>= 5.2.4)
@ -463,7 +463,7 @@ GEM
temple (0.8.2) temple (0.8.2)
thor (1.1.0) thor (1.1.0)
tilt (2.0.10) tilt (2.0.10)
truemail (2.4.4) truemail (2.4.6)
simpleidn (~> 0.2.1) simpleidn (~> 0.2.1)
tzinfo (2.0.4) tzinfo (2.0.4)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)

View file

@ -24,9 +24,8 @@ module Epp
# SELECT messages.id, domains.name, messages.body FROM messages LEFT OUTER # SELECT messages.id, domains.name, messages.body FROM messages LEFT OUTER
# JOIN domains ON attached_obj_id::INTEGER = domains.id # JOIN domains ON attached_obj_id::INTEGER = domains.id
# WHERE attached_obj_type = 'Epp::Domain' AND name IS NULL; # WHERE attached_obj_type = 'Epp::Domain' AND name IS NULL;
message = 'orphan message, domain deleted, registrar should dequeue: '
Rails.logger.error 'orphan message, error ignored: ' + problem.to_s Rails.logger.error message + problem.to_s
# now we should dequeue or delete the messages avoid duplicate log alarms
end end
end end

View file

@ -64,6 +64,7 @@ class Registrar
def info def info
authorize! :info, Depp::Domain authorize! :info, Depp::Domain
@data = @domain.info(params[:domain_name]) if params[:domain_name] @data = @domain.info(params[:domain_name]) if params[:domain_name]
@pending_delete = domain_delete_pending(@data)
@client_holded = client_holded(@data) @client_holded = client_holded(@data)
if response_ok? if response_ok?
render 'info' render 'info'
@ -131,6 +132,7 @@ class Registrar
@data = @domain.delete(params[:domain]) @data = @domain.delete(params[:domain])
@results = @data.css('result') @results = @data.css('result')
if response_ok? if response_ok?
flash[:notice] = t('.deleting_request')
redirect_to info_registrar_domains_url(domain_name: params[:domain][:name]) redirect_to info_registrar_domains_url(domain_name: params[:domain][:name])
else else
params[:domain_name] = params[:domain][:name] params[:domain_name] = params[:domain][:name]
@ -182,6 +184,11 @@ class Registrar
&.any? { |status| status == DomainStatus::CLIENT_HOLD } &.any? { |status| status == DomainStatus::CLIENT_HOLD }
end end
def domain_delete_pending(data)
data.css('status')&.map { |element| element.attribute('s').value }
&.any? { |status| status.include?(DomainStatus::PENDING_DELETE) }
end
def contacts def contacts
current_registrar_user.registrar.contacts current_registrar_user.registrar.contacts
end end

View file

@ -48,7 +48,7 @@ module Repp
api :PUT, '/repp/v1/registrar/notifications' api :PUT, '/repp/v1/registrar/notifications'
desc 'Mark poll message as read' desc 'Mark poll message as read'
param :notification, Hash, required: true do param :notification, Hash, required: true do
param :read, [true], required: true, desc: 'Set as true to mark as read' param :read, [true, 'true'], required: true, desc: 'Set as true to mark as read'
end end
def update def update
# rubocop:disable Style/AndOr # rubocop:disable Style/AndOr

View file

@ -2,10 +2,12 @@ module Domains
module CancelForceDelete module CancelForceDelete
class RemoveForceDeleteStatuses < Base class RemoveForceDeleteStatuses < Base
def execute def execute
domain.statuses.delete(DomainStatus::FORCE_DELETE) domain_statuses = [DomainStatus::FORCE_DELETE,
domain.statuses.delete(DomainStatus::SERVER_RENEW_PROHIBITED) DomainStatus::SERVER_RENEW_PROHIBITED,
domain.statuses.delete(DomainStatus::SERVER_TRANSFER_PROHIBITED) DomainStatus::SERVER_TRANSFER_PROHIBITED,
domain.statuses.delete(DomainStatus::CLIENT_HOLD) DomainStatus::CLIENT_HOLD]
rejected_statuses = domain.statuses.reject { |a| domain_statuses.include? a }
domain.statuses = rejected_statuses
domain.save(validate: false) domain.save(validate: false)
end end
end end

View file

@ -2,8 +2,9 @@ module Domains
module CancelForceDelete module CancelForceDelete
class RestoreStatusesBeforeForceDelete < Base class RestoreStatusesBeforeForceDelete < Base
def execute def execute
domain.statuses = domain.statuses_before_force_delete domain.statuses = domain.force_delete_domain_statuses_history || []
domain.statuses_before_force_delete = nil domain.statuses_before_force_delete = nil
domain.force_delete_domain_statuses_history = nil
domain.save(validate: false) domain.save(validate: false)
end end
end end

View file

@ -6,6 +6,7 @@ module Domains
DomainStatus::SERVER_TRANSFER_PROHIBITED].freeze DomainStatus::SERVER_TRANSFER_PROHIBITED].freeze
def execute def execute
domain.force_delete_domain_statuses_history = domain.statuses
domain.statuses_before_force_delete = domain.statuses domain.statuses_before_force_delete = domain.statuses
domain.statuses |= STATUSES_TO_SET domain.statuses |= STATUSES_TO_SET
domain.save(validate: false) domain.save(validate: false)

View file

@ -0,0 +1,36 @@
class MigrateBeforeForceDeleteStatusesJob < ApplicationJob
def perform
logger.info 'Ran MigrateBeforeForceDeleteStatusesJob!'
domains = Domain.where.not(statuses_before_force_delete: nil)
logger.info "Total domains are #{domains.count}"
interate_domain_in_batches(domains)
end
private
def interate_domain_in_batches(domains)
count = 0
domains.find_in_batches do |domain_batches|
count += domain_batches.count
logger.info "Proccesing #{count} domains of #{domains.count}"
domain_batches.each do |domain|
migrate_data_to_statuses_history(domain)
end
end
end
def migrate_data_to_statuses_history(domain)
domain.update(force_delete_domain_statuses_history: domain.statuses_before_force_delete)
rescue StandardError => e
logger.warn "#{domain.name} crashed!"
logger.warn e.to_s
raise e
end
def logger
@logger ||= Logger.new(Rails.root.join('log', 'migrate_before_force_delete_statuses.log'))
end
end

View file

@ -0,0 +1,36 @@
class MigrateStatusesToDomainHistoryJob < ApplicationJob
def perform
logger.info 'Ran MigrateStatusesToDomainHistoryJob!'
domains = Domain.where(locked_by_registrant_at: nil)
logger.info "Total domains are #{domains.count}"
interate_domain_in_batches(domains)
end
private
def interate_domain_in_batches(domains)
count = 0
domains.find_in_batches do |domain_batches|
count += domain_batches.count
logger.info "Proccesing #{count} domains of #{domains.count}"
domain_batches.each do |domain|
migrate_data_to_admin_store_field(domain)
end
end
end
def migrate_data_to_admin_store_field(domain)
domain.update(admin_store_statuses_history: domain.statuses)
rescue StandardError => e
logger.warn "#{domain.name} crashed!"
logger.warn e.to_s
raise e
end
def logger
@logger ||= Logger.new(Rails.root.join('log', 'migrate_statuses_to_domain_history.log'))
end
end

View file

@ -59,7 +59,6 @@ class BankTransaction < ApplicationRecord
end end
invoice = Invoice.find_by(number: invoice_no) invoice = Invoice.find_by(number: invoice_no)
errors.add(:base, I18n.t('invoice_was_not_found')) unless invoice
validate_invoice_data(invoice) validate_invoice_data(invoice)
return if errors.any? return if errors.any?
@ -68,6 +67,11 @@ class BankTransaction < ApplicationRecord
end end
def validate_invoice_data(invoice) def validate_invoice_data(invoice)
unless invoice
errors.add(:base, I18n.t('invoice_was_not_found'))
return
end
if invoice.paid? if invoice.paid?
errors.add(:base, I18n.t('invoice_is_already_binded')) errors.add(:base, I18n.t('invoice_is_already_binded'))
return return

View file

@ -1,6 +1,10 @@
module Domain::ForceDelete # rubocop:disable Metrics/ModuleLength module Domain::ForceDelete
extend ActiveSupport::Concern extend ActiveSupport::Concern
FORCE_DELETE_STATUSES = [DomainStatus::FORCE_DELETE,
DomainStatus::SERVER_RENEW_PROHIBITED,
DomainStatus::SERVER_TRANSFER_PROHIBITED].freeze
included do included do
store_accessor :force_delete_data, store_accessor :force_delete_data,
:force_delete_type, :force_delete_type,

View file

@ -36,9 +36,10 @@ module Domain::RegistryLockable
transaction do transaction do
LOCK_STATUSES.each do |domain_status| LOCK_STATUSES.each do |domain_status|
statuses.delete(domain_status) statuses.delete([domain_status])
end end
self.locked_by_registrant_at = nil self.locked_by_registrant_at = nil
self.statuses = admin_store_statuses_history || []
alert_registrar_lock_changes!(lock: false) alert_registrar_lock_changes!(lock: false)
save! save!

View file

@ -28,9 +28,6 @@ class Contact < ApplicationRecord
.where('success = false and verified_at IS NOT NULL') .where('success = false and verified_at IS NOT NULL')
} }
NAME_REGEXP = /([\u00A1-\u00B3\u00B5-\u00BF\u0021-\u0026\u0028-\u002C\u003A-\u0040]|
[\u005B-\u005F\u007B-\u007E\u2040-\u206F\u20A0-\u20BF\u2100-\u218F])/x.freeze
validates :name, :email, presence: true validates :name, :email, presence: true
validates :name, format: { without: NAME_REGEXP, message: :invalid }, if: -> { priv? } validates :name, format: { without: NAME_REGEXP, message: :invalid }, if: -> { priv? }

View file

@ -13,20 +13,22 @@ class Contact::Ident
validates :type, presence: true, inclusion: { in: proc { types } } validates :type, presence: true, inclusion: { in: proc { types } }
validates :country_code, presence: true, iso31661_alpha2: true validates :country_code, presence: true, iso31661_alpha2: true
validates_with MismatchValidator validates_with MismatchValidator
validates_with BirthDateValidator, if: :birthday?
def self.epp_code_map def self.epp_code_map
{ {
'2003' => [ '2003' => [
[:code, :blank], %i[code blank],
[:type, :blank], %i[type blank],
[:country_code, :blank] %i[country_code blank],
], ],
'2005' => [ '2005' => [
[:base, :mismatch], %i[base mismatch],
[:code, :invalid_national_id], %i[code invalid_national_id],
[:code, :invalid_reg_no], %i[code invalid_reg_no],
[:code, :invalid_iso8601_date], %i[code invalid_iso8601_date],
[:country_code, :invalid_iso31661_alpha2] %i[code invalid_birth_date],
%i[country_code invalid_iso31661_alpha2],
] ]
} }
end end

View file

@ -22,6 +22,10 @@ class Domain < ApplicationRecord
alias_attribute :auth_info, :transfer_code # Old attribute name; for PaperTrail alias_attribute :auth_info, :transfer_code # Old attribute name; for PaperTrail
alias_attribute :registered_at, :created_at alias_attribute :registered_at, :created_at
store_accessor :json_statuses_history,
:force_delete_domain_statuses_history,
:admin_store_statuses_history
# TODO: whois requests ip whitelist for full info for own domains and partial info for other domains # TODO: whois requests ip whitelist for full info for own domains and partial info for other domains
# TODO: most inputs should be trimmed before validatation, probably some global logic? # TODO: most inputs should be trimmed before validatation, probably some global logic?
@ -549,8 +553,22 @@ class Domain < ApplicationRecord
statuses.include?(DomainStatus::FORCE_DELETE) statuses.include?(DomainStatus::FORCE_DELETE)
end end
def update_unless_locked_by_registrant(update)
update(admin_store_statuses_history: update) unless locked_by_registrant?
end
def update_not_by_locked_statuses(update)
return unless locked_by_registrant?
result = update.reject { |status| RegistryLockable::LOCK_STATUSES.include? status }
update(admin_store_statuses_history: result)
end
# special handling for admin changing status # special handling for admin changing status
def admin_status_update(update) def admin_status_update(update)
update_unless_locked_by_registrant(update)
update_not_by_locked_statuses(update)
# check for deleted status # check for deleted status
statuses.each do |s| statuses.each do |s|
unless update.include? s unless update.include? s

View file

@ -0,0 +1,26 @@
class Contact::Ident::BirthDateValidator < ActiveModel::Validator
VALID_BIRTH_DATE_FROM = Time.zone.today - 150.years
VALID_BIRTH_DATE_TO = Time.zone.tomorrow
def validate(record)
record.errors.add(:code, :invalid_birth_date) if birth_date_wrong?(record)
end
private
def birth_date_wrong?(record)
return unless record.birthday?
begin
Date.parse(record.code)
rescue ArgumentError
return true
end
contact_ident_date = Date.parse(record.code)
valid_time_range = VALID_BIRTH_DATE_FROM...VALID_BIRTH_DATE_TO
return if valid_time_range.cover?(contact_ident_date)
true
end
end

View file

@ -14,7 +14,7 @@
- opts = [[t(:choose),''], 'contact', 'domain', 'poll'] - opts = [[t(:choose),''], 'contact', 'domain', 'poll']
- opts += [params[:q][:request_object_cont]] if params[:q].present? && params[:q][:request_object_cont].present? - opts += [params[:q][:request_object_cont]] if params[:q].present? && params[:q][:request_object_cont].present?
= f.label :request_object = f.label :request_object
= f.select :request_object_cont, opts, {}, class: 'form-control js-combobox', placeholder: t(:choose) = f.select :request_object_cont, opts, {}, class: 'form-control selectize_create', placeholder: t(:choose)
.col-md-3 .col-md-3
.form-group .form-group
= f.label :request_successful = f.label :request_successful

View file

@ -15,9 +15,7 @@
= f.label :ident_country_code, t(:country) + '*' = f.label :ident_country_code, t(:country) + '*'
.col-md-7 .col-md-7
- if ident_complete && @contact.persisted? && f.object.ident_country_code.present? - if ident_complete && @contact.persisted? && f.object.ident_country_code.present?
.disabled-value = f.text_field :ident_country_code, value: f.object.ident_country_code, :readonly => true
= Country.new(f.object.ident_country_code).try(:to_s)
= " [#{f.object.ident_country_code}]"
- else - else
= f.select(:ident_country_code, ApplicationController.helpers.all_country_options(country_selected), {}, = f.select(:ident_country_code, ApplicationController.helpers.all_country_options(country_selected), {},
class: 'js-ident-country-code', required: true) class: 'js-ident-country-code', required: true)
@ -27,9 +25,7 @@
= f.label :ident_type, t(:type) + '*' = f.label :ident_type, t(:type) + '*'
.col-md-7 .col-md-7
- if ident_complete && @contact.persisted? && f.object.ident_type.present? - if ident_complete && @contact.persisted? && f.object.ident_type.present?
.disabled-value = f.text_field :ident_type, value: f.object.ident_type, :readonly => true
= Depp::Contact.type_string(f.object.ident_type)
= " [#{f.object.ident_type}]"
- else - else
= f.select(:ident_type, Depp::Contact::SELECTION_TYPES, { selected: type_selected }, = f.select(:ident_type, Depp::Contact::SELECTION_TYPES, { selected: type_selected },
class: 'js-ident-type', required: true) class: 'js-ident-type', required: true)
@ -39,8 +35,7 @@
= f.label :ident, t(:ident) + '*' = f.label :ident, t(:ident) + '*'
.col-md-7 .col-md-7
- if ident_complete && @contact.persisted? && f.object.ident.present? - if ident_complete && @contact.persisted? && f.object.ident.present?
.disabled-value = f.text_field :ident, value: f.object.ident, :readonly => true
= f.object.ident
- else - else
= f.text_field :ident, class: 'form-control', required: true = f.text_field :ident, class: 'form-control', required: true
- tip_visibility = f.object.ident_type == 'birthday' ? '' : 'display: none' - tip_visibility = f.object.ident_type == 'birthday' ? '' : 'display: none'

View file

@ -7,7 +7,9 @@
class: 'btn btn-primary btn-xs' %> class: 'btn btn-primary btn-xs' %>
<%= link_to t('.renew_btn'), renew_registrar_domains_path(domain_name: domain.name), <%= link_to t('.renew_btn'), renew_registrar_domains_path(domain_name: domain.name),
class: 'btn btn-default btn-xs' %> class: 'btn btn-default btn-xs' %>
<% unless (domain.statuses & %w[pendingDelete pendingDeleteConfirmation]).any? %>
<%= link_to t('.delete_btn'), delete_registrar_domains_path(domain_name: domain.name), <%= link_to t('.delete_btn'), delete_registrar_domains_path(domain_name: domain.name),
class: 'btn btn-default btn-xs' %> class: 'btn btn-default btn-xs' %>
<% end %>
</td> </td>
</tr> </tr>

View file

@ -4,8 +4,10 @@
class: 'btn btn-default') %> class: 'btn btn-default') %>
<%= link_to(t(:renew), renew_registrar_domains_path(domain_name: params[:domain_name]), <%= link_to(t(:renew), renew_registrar_domains_path(domain_name: params[:domain_name]),
class: 'btn btn-default') %> class: 'btn btn-default') %>
<% unless @pending_delete %>
<%= link_to(t(:delete), delete_registrar_domains_path(domain_name: params[:domain_name]), <%= link_to(t(:delete), delete_registrar_domains_path(domain_name: params[:domain_name]),
class: 'btn btn-default') %> class: 'btn btn-default') %>
<% end %>
<% if @client_holded %> <% if @client_holded %>
<%= link_to(t(:remove_client_hold), remove_hold_registrar_domains_path(domain_name: params[:domain_name]), <%= link_to(t(:remove_client_hold), remove_hold_registrar_domains_path(domain_name: params[:domain_name]),
class: 'btn btn-default') %> class: 'btn btn-default') %>

View file

@ -9,3 +9,4 @@ en:
code: code:
invalid_national_id: does not conform to national identification number format of %{country} invalid_national_id: does not conform to national identification number format of %{country}
invalid_reg_no: does not conform to registration number format of %{country} invalid_reg_no: does not conform to registration number format of %{country}
invalid_birth_date: Birth date is invalid, age must be over 0 and under 150

View file

@ -16,6 +16,9 @@ en:
info: info:
transfer_btn: Transfer transfer_btn: Transfer
destroy:
deleting_request: Domain deletion request was sent
search_form: search_form:
download_btn: Download CSV download_btn: Download CSV
reset_btn: Reset reset_btn: Reset

View file

@ -0,0 +1,6 @@
class AddJsonStatusesHistoryFieldToDomain < ActiveRecord::Migration[6.1]
def change
add_column :domains, :json_statuses_history, :jsonb, if_not_exists: true
add_index :domains, :json_statuses_history, using: :gin, if_not_exists: true
end
end

View file

@ -933,7 +933,8 @@ CREATE TABLE public.domains (
uuid uuid DEFAULT public.gen_random_uuid() NOT NULL, uuid uuid DEFAULT public.gen_random_uuid() NOT NULL,
locked_by_registrant_at timestamp without time zone, locked_by_registrant_at timestamp without time zone,
force_delete_start timestamp without time zone, force_delete_start timestamp without time zone,
force_delete_data public.hstore force_delete_data public.hstore,
json_statuses_history jsonb
); );
@ -3985,6 +3986,13 @@ CREATE INDEX index_domain_transfers_on_domain_id ON public.domain_transfers USIN
CREATE INDEX index_domains_on_delete_date ON public.domains USING btree (delete_date); CREATE INDEX index_domains_on_delete_date ON public.domains USING btree (delete_date);
--
-- Name: index_domains_on_json_statuses_history; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_domains_on_json_statuses_history ON public.domains USING gin (json_statuses_history);
-- --
-- Name: index_domains_on_name; Type: INDEX; Schema: public; Owner: - -- Name: index_domains_on_name; Type: INDEX; Schema: public; Owner: -
-- --
@ -5152,6 +5160,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200917104213'), ('20200917104213'),
('20200921084356'), ('20200921084356'),
('20210215101019'), ('20210215101019'),
('20210616112332'); ('20210616112332'),
('20210708131814');

View file

@ -0,0 +1,10 @@
namespace :migrate_domain_statuses do
desc 'Starts collect invalid validation contacts'
task fd_domains: :environment do
MigrateBeforeForceDeleteStatusesJob.perform_later
end
task admin_status_history: :environment do
MigrateStatusesToDomainHistoryJob.perform_later
end
end

View file

@ -81,6 +81,67 @@ class EppContactCreateBaseTest < EppTestCase
assert_epp_response :parameter_value_syntax_error assert_epp_response :parameter_value_syntax_error
end end
def test_responses_with_error_on_invalid_birthday_date
name = 'new'
email = 'new@registrar.test'
phone = '+1.2'
birthday_wrong_format = '1111-22-33'
birthday_above_valid_range = '1800-01-01'
birthday_below_valid_range = '2050-07-09'
request_xml = <<-XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
<command>
<create>
<contact:create xmlns:contact="https://epp.tld.ee/schema/contact-ee-1.1.xsd">
<contact:postalInfo>
<contact:name>#{name}</contact:name>
</contact:postalInfo>
<contact:voice>#{phone}</contact:voice>
<contact:email>#{email}</contact:email>
</contact:create>
</create>
<extension>
<eis:extdata xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd">
<eis:ident type="birthday" cc="LV">#{birthday_wrong_format}</eis:ident>
</eis:extdata>
</extension>
</command>
</epp>
XML
assert_no_difference 'Contact.count' do
post epp_create_path, params: { frame: request_xml },
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
end
response_xml = Nokogiri::XML(response.body)
assert_correct_against_schema response_xml
assert_epp_response :parameter_value_syntax_error
request_xml.sub! ">#{birthday_wrong_format}<", ">#{birthday_above_valid_range}<"
assert_no_difference 'Contact.count' do
post epp_create_path, params: { frame: request_xml },
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
end
response_xml = Nokogiri::XML(response.body)
assert_correct_against_schema response_xml
assert_epp_response :parameter_value_syntax_error
request_xml.sub! ">#{birthday_above_valid_range}<", ">#{birthday_below_valid_range}<"
assert_no_difference 'Contact.count' do
post epp_create_path, params: { frame: request_xml },
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
end
response_xml = Nokogiri::XML(response.body)
assert_correct_against_schema response_xml
assert_epp_response :parameter_value_syntax_error
end
def test_responces_error_with_email_error def test_responces_error_with_email_error
name = 'new' name = 'new'
email = 'new@registrar@test' email = 'new@registrar@test'

View file

@ -588,6 +588,50 @@ class EppDomainUpdateBaseTest < EppTestCase
assert_no_emails assert_no_emails
end end
def test_makes_update_if_was_forcedelete
contact = @domain.contacts.first
contact.update_attribute(:email, '`@outlook.test')
contact.email_verification.verify
assert contact.email_verification_failed?
@domain.reload
assert @domain.force_delete_scheduled?
@domain.update_attribute(:statuses_before_force_delete, nil)
Setting.request_confirmation_on_registrant_change_enabled = true
new_registrant = contacts(:william).becomes(Registrant)
assert_not_equal new_registrant, @domain.registrant
request_xml = <<-XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="#{Xsd::Schema.filename(for_prefix: 'epp-ee', for_version: '1.0')}">
<command>
<update>
<domain:update xmlns:domain="#{Xsd::Schema.filename(for_prefix: 'domain-ee', for_version: '1.1')}">
<domain:name>#{@domain.name}</domain:name>
<domain:chg>
<domain:registrant verified="yes">#{new_registrant.code}</domain:registrant>
</domain:chg>
</domain:update>
</update>
<extension>
<eis:extdata xmlns:eis="#{Xsd::Schema.filename(for_prefix: 'eis', for_version: '1.0')}">
<eis:legalDocument type="pdf">#{'test' * 2000}</eis:legalDocument>
</eis:extdata>
</extension>
</command>
</epp>
XML
post epp_update_path, params: { frame: request_xml },
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
@domain.reload
response_xml = Nokogiri::XML(response.body)
assert_correct_against_schema response_xml
assert_epp_response :completed_successfully
end
def test_clears_force_delete_when_registrar_changed def test_clears_force_delete_when_registrar_changed
Setting.request_confirmation_on_registrant_change_enabled = true Setting.request_confirmation_on_registrant_change_enabled = true
new_registrant = contacts(:william).becomes(Registrant) new_registrant = contacts(:william).becomes(Registrant)

View file

@ -0,0 +1,27 @@
require 'test_helper'
class MigrateBeforeForceDeleteStatusesJobTest < ActiveJob::TestCase
setup do
travel_to Time.zone.parse('2010-07-05')
@domain = domains(:shop)
end
def test_migrate_data_before_force_delete
@domain.update(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED])
@domain.reload
assert @domain.statuses.include? DomainStatus::SERVER_UPDATE_PROHIBITED
@domain.schedule_force_delete(type: :soft)
@domain.reload
assert @domain.force_delete_scheduled?
perform_enqueued_jobs do
MigrateBeforeForceDeleteStatusesJob.perform_later
end
@domain.reload
assert @domain.force_delete_domain_statuses_history.include? DomainStatus::SERVER_UPDATE_PROHIBITED
end
end

View file

@ -0,0 +1,22 @@
require 'test_helper'
class MigrateBeforeForceDeleteStatusesJobTest < ActiveJob::TestCase
setup do
travel_to Time.zone.parse('2010-07-05')
@domain = domains(:shop)
end
def test_migrate_statuses_to_domain_history_job
@domain.update(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED])
@domain.reload
assert @domain.statuses.include? DomainStatus::SERVER_UPDATE_PROHIBITED
perform_enqueued_jobs do
MigrateStatusesToDomainHistoryJob.perform_later
end
@domain.reload
assert @domain.admin_store_statuses_history.include? DomainStatus::SERVER_UPDATE_PROHIBITED
end
end

View file

@ -136,6 +136,12 @@ class BankTransactionTest < ActiveSupport::TestCase
assert transaction.errors.full_messages.include?('Invoice and transaction sums do not match') assert transaction.errors.full_messages.include?('Invoice and transaction sums do not match')
end end
def test_binds_without_invoice_no
transaction = BankTransaction.new(sum: 9)
transaction.bind_invoice('')
assert transaction.errors.full_messages.include?('Invoice was not found')
end
def test_overpayment_is_not_matched_with_invoice def test_overpayment_is_not_matched_with_invoice
create_payable_invoice(number: '2222', total: 10) create_payable_invoice(number: '2222', total: 10)
transaction = BankTransaction.new(sum: 11) transaction = BankTransaction.new(sum: 11)

View file

@ -12,6 +12,29 @@ class ForceDeleteTest < ActionMailer::TestCase
Truemail.configure.default_validation_type = @old_validation_type Truemail.configure.default_validation_type = @old_validation_type
end end
def test_restore_domain_statuses_after_soft_force_delete
@domain.update(statuses: [DomainStatus::SERVER_RENEW_PROHIBITED])
@domain.schedule_force_delete(type: :soft)
assert @domain.force_delete_scheduled?
assert @domain.force_delete_domain_statuses_history.include? DomainStatus::SERVER_RENEW_PROHIBITED
@domain.cancel_force_delete
assert @domain.statuses.include? DomainStatus::SERVER_RENEW_PROHIBITED
end
def test_clear_force_delete_domain_statuses_history
@domain.update(statuses: [DomainStatus::SERVER_RENEW_PROHIBITED])
@domain.schedule_force_delete(type: :soft)
assert @domain.force_delete_scheduled?
assert @domain.force_delete_domain_statuses_history.include? DomainStatus::SERVER_RENEW_PROHIBITED
@domain.cancel_force_delete
assert_nil @domain.force_delete_domain_statuses_history
end
def test_schedules_force_delete_fast_track def test_schedules_force_delete_fast_track
assert_not @domain.force_delete_scheduled? assert_not @domain.force_delete_scheduled?
travel_to Time.zone.parse('2010-07-05') travel_to Time.zone.parse('2010-07-05')
@ -56,7 +79,7 @@ class ForceDeleteTest < ActionMailer::TestCase
statuses_to_be_added = [ statuses_to_be_added = [
DomainStatus::FORCE_DELETE, DomainStatus::FORCE_DELETE,
DomainStatus::SERVER_RENEW_PROHIBITED, DomainStatus::SERVER_RENEW_PROHIBITED,
DomainStatus::SERVER_TRANSFER_PROHIBITED, DomainStatus::SERVER_TRANSFER_PROHIBITED
] ]
@domain.schedule_force_delete(type: :soft) @domain.schedule_force_delete(type: :soft)
@ -68,7 +91,7 @@ class ForceDeleteTest < ActionMailer::TestCase
statuses_to_be_added = [ statuses_to_be_added = [
DomainStatus::FORCE_DELETE, DomainStatus::FORCE_DELETE,
DomainStatus::SERVER_RENEW_PROHIBITED, DomainStatus::SERVER_RENEW_PROHIBITED,
DomainStatus::SERVER_TRANSFER_PROHIBITED, DomainStatus::SERVER_TRANSFER_PROHIBITED
] ]
@domain.schedule_force_delete(type: :fast_track) @domain.schedule_force_delete(type: :fast_track)
@ -79,7 +102,7 @@ class ForceDeleteTest < ActionMailer::TestCase
def test_scheduling_force_delete_allows_domain_deletion def test_scheduling_force_delete_allows_domain_deletion
statuses_to_be_removed = [ statuses_to_be_removed = [
DomainStatus::CLIENT_DELETE_PROHIBITED, DomainStatus::CLIENT_DELETE_PROHIBITED,
DomainStatus::SERVER_DELETE_PROHIBITED, DomainStatus::SERVER_DELETE_PROHIBITED
] ]
@domain.statuses = statuses_to_be_removed + %w[other-status] @domain.statuses = statuses_to_be_removed + %w[other-status]
@ -94,7 +117,7 @@ class ForceDeleteTest < ActionMailer::TestCase
DomainStatus::PENDING_UPDATE, DomainStatus::PENDING_UPDATE,
DomainStatus::PENDING_TRANSFER, DomainStatus::PENDING_TRANSFER,
DomainStatus::PENDING_RENEW, DomainStatus::PENDING_RENEW,
DomainStatus::PENDING_CREATE, DomainStatus::PENDING_CREATE
] ]
@domain.statuses = statuses_to_be_removed + %w[other-status] @domain.statuses = statuses_to_be_removed + %w[other-status]
@ -122,7 +145,7 @@ class ForceDeleteTest < ActionMailer::TestCase
assert_not result.valid? assert_not result.valid?
assert_not @domain.force_delete_scheduled? assert_not @domain.force_delete_scheduled?
message = ["Force delete procedure cannot be scheduled while a domain is discarded"] message = ['Force delete procedure cannot be scheduled while a domain is discarded']
assert_equal message, result.errors.messages[:domain] assert_equal message, result.errors.messages[:domain]
end end
@ -149,9 +172,9 @@ class ForceDeleteTest < ActionMailer::TestCase
def test_force_delete_does_not_double_statuses def test_force_delete_does_not_double_statuses
statuses = [ statuses = [
DomainStatus::FORCE_DELETE, DomainStatus::FORCE_DELETE,
DomainStatus::SERVER_RENEW_PROHIBITED, DomainStatus::SERVER_RENEW_PROHIBITED,
DomainStatus::SERVER_TRANSFER_PROHIBITED, DomainStatus::SERVER_TRANSFER_PROHIBITED
] ]
@domain.statuses = @domain.statuses + statuses @domain.statuses = @domain.statuses + statuses
@domain.save! @domain.save!
@ -177,8 +200,8 @@ class ForceDeleteTest < ActionMailer::TestCase
def test_cancelling_force_delete_keeps_previous_statuses def test_cancelling_force_delete_keeps_previous_statuses
statuses = [ statuses = [
DomainStatus::SERVER_RENEW_PROHIBITED, DomainStatus::SERVER_RENEW_PROHIBITED,
DomainStatus::SERVER_TRANSFER_PROHIBITED, DomainStatus::SERVER_TRANSFER_PROHIBITED
] ]
@domain.statuses = statuses @domain.statuses = statuses
@ -479,7 +502,7 @@ class ForceDeleteTest < ActionMailer::TestCase
@bounced_mail.bounce_subtype = 'General' @bounced_mail.bounce_subtype = 'General'
@bounced_mail.action = 'failed' @bounced_mail.action = 'failed'
@bounced_mail.status = '5.1.1' @bounced_mail.status = '5.1.1'
@bounced_mail.diagnostic = 'smtp; 550 5.1.1 user unknown' @bounced_mail.diagnostic = 'smtp; 550 5.1.1 user unknown'
@bounced_mail.save! @bounced_mail.save!
end end
end end

View file

@ -11,12 +11,62 @@ class DomainRegistryLockableTest < ActiveSupport::TestCase
refute(@domain.locked_by_registrant?) refute(@domain.locked_by_registrant?)
@domain.update(statuses: [DomainStatus::SERVER_TRANSFER_PROHIBITED]) @domain.update(statuses: [DomainStatus::SERVER_TRANSFER_PROHIBITED])
@domain.apply_registry_lock #Raise validation error @domain.apply_registry_lock # Raise validation error
check_statuses_lockable_domain check_statuses_lockable_domain
assert(@domain.locked_by_registrant?) assert(@domain.locked_by_registrant?)
end end
def test_remove_lockalable_statuses_after_admin_intervention
@domain.apply_registry_lock
assert @domain.locked_by_registrant?
assert_equal @domain.statuses.sort, Domain::RegistryLockable::LOCK_STATUSES.sort
deleted_status = @domain.statuses - [DomainStatus::SERVER_DELETE_PROHIBITED]
@domain.update(statuses: deleted_status)
assert_not @domain.locked_by_registrant?
@domain.apply_registry_lock
assert @domain.locked_by_registrant?
@domain.remove_registry_lock
assert_not @domain.statuses.include? DomainStatus::SERVER_UPDATE_PROHIBITED
assert_not @domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED
assert_not @domain.statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED
end
def test_restore_domain_statuses_after_unlock
@domain.statuses = [DomainStatus::SERVER_UPDATE_PROHIBITED]
@domain.admin_store_statuses_history = [DomainStatus::SERVER_UPDATE_PROHIBITED]
@domain.save
assert @domain.admin_store_statuses_history.include? DomainStatus::SERVER_UPDATE_PROHIBITED
@domain.apply_registry_lock
assert @domain.locked_by_registrant?
assert_equal @domain.statuses.sort, Domain::RegistryLockable::LOCK_STATUSES.sort
@domain.remove_registry_lock
assert @domain.statuses.include? DomainStatus::SERVER_UPDATE_PROHIBITED
assert_not @domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED
assert_not @domain.statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED
end
def test_add_additinal_status_for_locked_domain
@domain.apply_registry_lock
assert @domain.locked_by_registrant?
assert_equal @domain.statuses.sort, Domain::RegistryLockable::LOCK_STATUSES.sort
@domain.statuses += [DomainStatus::SERVER_RENEW_PROHIBITED]
@domain.admin_store_statuses_history = [DomainStatus::SERVER_RENEW_PROHIBITED]
@domain.save
@domain.remove_registry_lock
assert @domain.statuses.include? DomainStatus::SERVER_RENEW_PROHIBITED
assert_not @domain.statuses.include? DomainStatus::SERVER_UPDATE_PROHIBITED
assert_not @domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED
assert_not @domain.statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED
end
def test_lockable_domain_if_remove_some_prohibited_status def test_lockable_domain_if_remove_some_prohibited_status
refute(@domain.locked_by_registrant?) refute(@domain.locked_by_registrant?)
@domain.apply_registry_lock @domain.apply_registry_lock
@ -29,7 +79,7 @@ class DomainRegistryLockableTest < ActiveSupport::TestCase
assert @domain.statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED assert @domain.statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED
assert @domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED assert @domain.statuses.include? DomainStatus::SERVER_TRANSFER_PROHIBITED
assert_not @domain.statuses.include? DomainStatus::SERVER_UPDATE_PROHIBITED assert_not @domain.statuses.include? DomainStatus::SERVER_UPDATE_PROHIBITED
assert_not(@domain.locked_by_registrant?) assert_not(@domain.locked_by_registrant?)
end end
@ -74,7 +124,7 @@ class DomainRegistryLockableTest < ActiveSupport::TestCase
@domain.remove_registry_lock @domain.remove_registry_lock
assert_equal(["ok"], @domain.statuses) assert_equal(['ok'], @domain.statuses)
refute(@domain.locked_by_registrant?) refute(@domain.locked_by_registrant?)
refute(@domain.locked_by_registrant_at) refute(@domain.locked_by_registrant_at)
end end
@ -100,8 +150,8 @@ class DomainRegistryLockableTest < ActiveSupport::TestCase
def check_statuses_lockable_domain def check_statuses_lockable_domain
lock_statuses = [DomainStatus::SERVER_UPDATE_PROHIBITED, lock_statuses = [DomainStatus::SERVER_UPDATE_PROHIBITED,
DomainStatus::SERVER_DELETE_PROHIBITED, DomainStatus::SERVER_DELETE_PROHIBITED,
DomainStatus::SERVER_TRANSFER_PROHIBITED] DomainStatus::SERVER_TRANSFER_PROHIBITED]
@domain.statuses.include? lock_statuses @domain.statuses.include? lock_statuses
end end

View file

@ -27,6 +27,17 @@ class DomainTest < ActiveSupport::TestCase
assert domains(:invalid).invalid? assert domains(:invalid).invalid?
end end
def test_valid_domain_statuses_history
@domain.force_delete_domain_statuses_history = [DomainStatus::SERVER_UPDATE_PROHIBITED,
DomainStatus::SERVER_TRANSFER_PROHIBITED]
@domain.admin_store_statuses_history = [DomainStatus::SERVER_UPDATE_PROHIBITED]
assert @domain.valid?
assert @domain.json_statuses_history['force_delete_domain_statuses_history'].include? 'serverUpdateProhibited'
assert @domain.json_statuses_history['force_delete_domain_statuses_history'].include? 'serverTransferProhibited'
assert_equal @domain.json_statuses_history['admin_store_statuses_history'], ['serverUpdateProhibited']
end
# https://www.internet.ee/domeenid/ee-domeenireeglid#domeeninimede-registreerimine # https://www.internet.ee/domeenid/ee-domeenireeglid#domeeninimede-registreerimine
def test_validates_name_format def test_validates_name_format
assert_equal dns_zones(:one).origin, 'test' assert_equal dns_zones(:one).origin, 'test'