mirror of
https://github.com/internetee/registry.git
synced 2025-07-30 06:26:15 +02:00
Merge pull request #2770 from internetee/2750-admin-contact-cannot-be-a-minor-clean
2750 admin contact cannot be a minor clean
This commit is contained in:
commit
5946afc729
12 changed files with 189 additions and 52 deletions
|
@ -1,4 +1,8 @@
|
|||
class AdminDomainContact < DomainContact
|
||||
include AgeValidation
|
||||
|
||||
validate :validate_contact_age
|
||||
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
def self.replace(current_contact, new_contact)
|
||||
|
@ -23,4 +27,14 @@ class AdminDomainContact < DomainContact
|
|||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
|
||||
private
|
||||
|
||||
def validate_contact_age
|
||||
return unless contact&.underage?
|
||||
|
||||
errors.add(:contact, I18n.t(
|
||||
'activerecord.errors.models.admin_domain_contact.contact_too_young'
|
||||
))
|
||||
end
|
||||
end
|
||||
|
|
53
app/models/concerns/age_validation.rb
Normal file
53
app/models/concerns/age_validation.rb
Normal file
|
@ -0,0 +1,53 @@
|
|||
module AgeValidation
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def underage?
|
||||
case ident_type
|
||||
when 'birthday'
|
||||
underage_by_birthday?
|
||||
when 'priv'
|
||||
underage_by_estonian_id?
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def underage_by_birthday?
|
||||
birth_date = Date.parse(ident)
|
||||
calculate_age(birth_date) < 18
|
||||
end
|
||||
|
||||
def underage_by_estonian_id?
|
||||
return false unless estonian_id?
|
||||
|
||||
birth_date = parse_estonian_id_birth_date(ident)
|
||||
calculate_age(birth_date) < 18
|
||||
end
|
||||
|
||||
def estonian_id?
|
||||
ident_country_code == 'EE' && ident.match?(/^\d{11}$/)
|
||||
end
|
||||
|
||||
def calculate_age(birth_date)
|
||||
((Time.zone.now - birth_date.to_time) / 1.year.seconds).floor
|
||||
end
|
||||
|
||||
def parse_estonian_id_birth_date(id_code)
|
||||
century_number = id_code[0].to_i
|
||||
year_digits = id_code[1..2]
|
||||
month = id_code[3..4]
|
||||
day = id_code[5..6]
|
||||
|
||||
birth_year = case century_number
|
||||
when 1, 2 then "18#{year_digits}"
|
||||
when 3, 4 then "19#{year_digits}"
|
||||
when 5, 6 then "20#{year_digits}"
|
||||
else
|
||||
raise ArgumentError, "Invalid century number in Estonian ID"
|
||||
end
|
||||
|
||||
Date.parse("#{birth_year}-#{month}-#{day}")
|
||||
end
|
||||
end
|
|
@ -10,6 +10,7 @@ class Contact < ApplicationRecord
|
|||
include Contact::Archivable
|
||||
include Contact::CompanyRegister
|
||||
include EmailVerifable
|
||||
include AgeValidation
|
||||
|
||||
belongs_to :original, class_name: 'Contact'
|
||||
belongs_to :registrar, required: true
|
||||
|
|
|
@ -12,6 +12,7 @@ class Domain < ApplicationRecord
|
|||
include Domain::Releasable
|
||||
include Domain::Disputable
|
||||
include Domain::BulkUpdatable
|
||||
include AgeValidation
|
||||
|
||||
PERIODS = [
|
||||
['3 months', '3m'],
|
||||
|
@ -866,7 +867,7 @@ class Domain < ApplicationRecord
|
|||
return true if registrant.org? && Setting.admin_contacts_required_for_org
|
||||
return false unless registrant.priv?
|
||||
|
||||
underage_registrant? && Setting.admin_contacts_required_for_minors
|
||||
registrant.underage? && Setting.admin_contacts_required_for_minors
|
||||
end
|
||||
|
||||
def require_tech_contacts?
|
||||
|
@ -876,51 +877,7 @@ class Domain < ApplicationRecord
|
|||
private
|
||||
|
||||
def underage_registrant?
|
||||
case registrant.ident_type
|
||||
when 'birthday'
|
||||
underage_by_birthday?
|
||||
when 'priv'
|
||||
underage_by_estonian_id?
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def underage_by_birthday?
|
||||
birth_date = Date.parse(registrant.ident)
|
||||
calculate_age(birth_date) < 18
|
||||
end
|
||||
|
||||
def underage_by_estonian_id?
|
||||
return false unless estonian_id?
|
||||
|
||||
birth_date = parse_estonian_id_birth_date(registrant.ident)
|
||||
calculate_age(birth_date) < 18
|
||||
end
|
||||
|
||||
def estonian_id?
|
||||
registrant.ident_country_code == 'EE' && registrant.ident.match?(/^\d{11}$/)
|
||||
end
|
||||
|
||||
def calculate_age(birth_date)
|
||||
((Time.zone.now - birth_date.to_time) / 1.year.seconds).floor
|
||||
end
|
||||
|
||||
def parse_estonian_id_birth_date(id_code)
|
||||
century_number = id_code[0].to_i
|
||||
year_digits = id_code[1..2]
|
||||
month = id_code[3..4]
|
||||
day = id_code[5..6]
|
||||
|
||||
birth_year = case century_number
|
||||
when 1, 2 then "18#{year_digits}"
|
||||
when 3, 4 then "19#{year_digits}"
|
||||
when 5, 6 then "20#{year_digits}"
|
||||
else
|
||||
raise ArgumentError, "Invalid century number in Estonian ID"
|
||||
end
|
||||
|
||||
Date.parse("#{birth_year}-#{month}-#{day}")
|
||||
registrant.underage?
|
||||
end
|
||||
|
||||
def validate_admin_contacts_ident_type
|
||||
|
|
|
@ -37,7 +37,12 @@ class Epp::Domain < Domain
|
|||
# validate registrant here as well
|
||||
([Contact.find(registrant.id)] + active_admins + active_techs).each do |x|
|
||||
unless x.valid?
|
||||
add_epp_error('2304', nil, nil, I18n.t(:contact_is_not_valid, value: x.try(:code)))
|
||||
if x.class.name == 'AdminDomainContact' && x.contact.underage?
|
||||
add_epp_error('2304', nil, nil, I18n.t('activerecord.errors.models.admin_domain_contact.contact_too_young'))
|
||||
else
|
||||
add_epp_error('2304', nil, nil, I18n.t(:contact_is_not_valid, value: x.try(:code)))
|
||||
end
|
||||
|
||||
ok = false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -160,6 +160,8 @@ en:
|
|||
ipv6:
|
||||
taken: 'has already been taken'
|
||||
|
||||
admin_domain_contact:
|
||||
contact_too_young: "Administrative contact must be at least 18 years old"
|
||||
|
||||
attributes:
|
||||
epp_domain: &epp_domain_attributes
|
||||
|
|
|
@ -23,11 +23,13 @@ class AdminAreaAdminUsersIntegrationTest < JavaScriptApplicationSystemTestCase
|
|||
createNewAdminUser(true)
|
||||
|
||||
visit admin_admin_users_path
|
||||
assert_selector 'a', text: 'test_user_name'
|
||||
click_on 'test_user_name'
|
||||
|
||||
assert_text 'General'
|
||||
click_on 'Edit'
|
||||
|
||||
assert_selector 'input[name*="password"]'
|
||||
fill_in 'Password', with: 'test_password'
|
||||
fill_in 'Password confirmation', with: 'test_password'
|
||||
|
||||
|
|
|
@ -597,7 +597,7 @@ class EppDomainCreateBaseTest < EppTestCase
|
|||
end
|
||||
|
||||
def test_registers_new_domain_with_required_attributes
|
||||
Setting.admin_contacts_allowed_ident_type = { 'org' => true, 'priv' => true, 'birthday' => true }
|
||||
Setting.admin_contacts_allowed_ident_type = { 'org' => true, 'priv' => true, 'birthday' => true }.to_json
|
||||
|
||||
now = Time.zone.parse('2010-07-05')
|
||||
travel_to now
|
||||
|
@ -647,7 +647,7 @@ class EppDomainCreateBaseTest < EppTestCase
|
|||
default_registration_period = 1.year + 1.day
|
||||
assert_equal now + default_registration_period, domain.expire_time
|
||||
|
||||
Setting.admin_contacts_allowed_ident_type = { 'org' => false, 'priv' => true, 'birthday' => true }
|
||||
Setting.admin_contacts_allowed_ident_type = { 'org' => false, 'priv' => true, 'birthday' => true }.to_json
|
||||
end
|
||||
|
||||
def test_registers_domain_without_legaldoc_if_optout
|
||||
|
|
|
@ -1032,7 +1032,7 @@ class EppDomainUpdateBaseTest < EppTestCase
|
|||
@domain.save!
|
||||
|
||||
# Change allowed types after domain is created
|
||||
Setting.admin_contacts_allowed_ident_type = { 'birthday' => true, 'priv' => true, 'org' => false }
|
||||
Setting.admin_contacts_allowed_ident_type = { 'birthday' => true, 'priv' => true, 'org' => false }.to_json
|
||||
|
||||
# Try to update domain with some other changes
|
||||
request_xml = <<-XML
|
||||
|
@ -1061,6 +1061,36 @@ class EppDomainUpdateBaseTest < EppTestCase
|
|||
assert_epp_response :completed_successfully
|
||||
end
|
||||
|
||||
def test_does_not_allow_underage_admin_contact
|
||||
admin_contact = contacts(:william)
|
||||
admin_contact.update!(
|
||||
ident_type: 'priv',
|
||||
ident: '61203150222',
|
||||
ident_country_code: 'EE'
|
||||
)
|
||||
|
||||
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.2')}">
|
||||
<domain:name>#{@domain.name}</domain:name>
|
||||
<domain:add>
|
||||
<domain:contact type="admin">#{admin_contact.code}</domain:contact>
|
||||
</domain:add>
|
||||
</domain:update>
|
||||
</update>
|
||||
</command>
|
||||
</epp>
|
||||
XML
|
||||
|
||||
post epp_update_path, params: { frame: request_xml },
|
||||
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
|
||||
|
||||
assert_epp_response :object_status_prohibits_operation
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def assert_verification_and_notification_emails
|
||||
|
|
|
@ -14,7 +14,7 @@ class DomainVersionTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
def test_assigns_creator_to_paper_trail_whodunnit
|
||||
Setting.admin_contacts_allowed_ident_type = { 'org' => true, 'priv' => true, 'birthday' => true }
|
||||
Setting.admin_contacts_allowed_ident_type = { 'org' => true, 'priv' => true, 'birthday' => true }.to_json
|
||||
duplicate_domain = prepare_duplicate_domain
|
||||
|
||||
PaperTrail.request.whodunnit = @user.id_role_username
|
||||
|
|
|
@ -14,4 +14,70 @@ class DomainContactTest < ActiveSupport::TestCase
|
|||
assert @domain_contact.value_typeahead, 'Jane'
|
||||
end
|
||||
|
||||
def test_validates_admin_contact_age_with_birthday
|
||||
admin_contact = contacts(:john)
|
||||
admin_contact.update!(
|
||||
ident_type: 'birthday',
|
||||
ident: (Time.zone.now - 16.years).strftime('%Y-%m-%d')
|
||||
)
|
||||
|
||||
domain_contact = AdminDomainContact.new(
|
||||
domain: domains(:shop),
|
||||
contact: admin_contact
|
||||
)
|
||||
|
||||
assert_not domain_contact.valid?
|
||||
assert_includes domain_contact.errors.full_messages,
|
||||
'Contact Administrative contact must be at least 18 years old'
|
||||
end
|
||||
|
||||
def test_validates_admin_contact_age_with_estonian_id
|
||||
admin_contact = contacts(:john)
|
||||
admin_contact.update!(
|
||||
ident_type: 'priv',
|
||||
ident: '61203150222',
|
||||
ident_country_code: 'EE'
|
||||
)
|
||||
|
||||
domain_contact = AdminDomainContact.new(
|
||||
domain: domains(:shop),
|
||||
contact: admin_contact
|
||||
)
|
||||
|
||||
assert_not domain_contact.valid?
|
||||
assert_includes domain_contact.errors.full_messages,
|
||||
'Contact Administrative contact must be at least 18 years old'
|
||||
end
|
||||
|
||||
def test_allows_adult_admin_contact_with_birthday
|
||||
admin_contact = contacts(:john)
|
||||
admin_contact.update!(
|
||||
ident_type: 'birthday',
|
||||
ident: (Time.zone.now - 20.years).strftime('%Y-%m-%d')
|
||||
)
|
||||
|
||||
domain_contact = AdminDomainContact.new(
|
||||
domain: domains(:shop),
|
||||
contact: admin_contact
|
||||
)
|
||||
|
||||
assert domain_contact.valid?
|
||||
end
|
||||
|
||||
def test_allows_adult_admin_contact_with_estonian_id
|
||||
admin_contact = contacts(:john)
|
||||
admin_contact.update!(
|
||||
ident_type: 'priv',
|
||||
ident: '38903111310',
|
||||
ident_country_code: 'EE'
|
||||
)
|
||||
|
||||
domain_contact = AdminDomainContact.new(
|
||||
domain: domains(:shop),
|
||||
contact: admin_contact
|
||||
)
|
||||
|
||||
assert domain_contact.valid?
|
||||
end
|
||||
|
||||
end
|
|
@ -587,7 +587,14 @@ class DomainTest < ActiveSupport::TestCase
|
|||
assert domain.invalid?
|
||||
assert_includes domain.errors.full_messages, 'Admin domain contacts Admin contacts count must be between 1-10'
|
||||
|
||||
domain.admin_domain_contacts.build(contact: contacts(:john))
|
||||
admin_contact = contacts(:john)
|
||||
admin_contact.update!(
|
||||
ident_type: 'priv',
|
||||
ident: '37810166020',
|
||||
ident_country_code: 'EE'
|
||||
)
|
||||
|
||||
domain.admin_domain_contacts.build(contact: admin_contact)
|
||||
assert domain.valid?
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue