From 576fa914b4112ed9f9bd9c7918d8fe88d055b059 Mon Sep 17 00:00:00 2001 From: Stas Date: Thu, 28 Apr 2016 13:15:13 +0300 Subject: [PATCH 1/8] 114677695-utf8_nameservers --- app/models/nameserver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb index ccedf0880..168b5129e 100644 --- a/app/models/nameserver.rb +++ b/app/models/nameserver.rb @@ -8,7 +8,7 @@ class Nameserver < ActiveRecord::Base # scope :owned_by_registrar, -> (registrar) { joins(:domain).where('domains.registrar_id = ?', registrar.id) } # rubocop: disable Metrics/LineLength - validates :hostname, format: { with: /\A(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\z/ } + validates :hostname, domain_name: true # validates :ipv4, format: { with: /\A(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\z/, allow_blank: true } # validates :ipv6, format: { with: /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/, allow_blank: true } validate :val_ipv4 From d04f558af55b4fa840e4d0c8f3425ebcf4ceca09 Mon Sep 17 00:00:00 2001 From: Stas Date: Fri, 29 Apr 2016 18:17:41 +0300 Subject: [PATCH 2/8] 114677695-converter_and_migration --- app/models/nameserver.rb | 10 +++++ ...9114732_add_puny_hostname_to_nameserver.rb | 9 ++++ lib/tasks/convert.rake | 42 +++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 db/migrate/20160429114732_add_puny_hostname_to_nameserver.rb diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb index 168b5129e..d86813908 100644 --- a/app/models/nameserver.rb +++ b/app/models/nameserver.rb @@ -16,6 +16,8 @@ class Nameserver < ActiveRecord::Base # rubocop: enable Metrics/LineLength before_validation :normalize_attributes + before_validation :hostname_to_utf + after_validation :add_hostname_puny delegate :name, to: :domain, prefix: true @@ -41,6 +43,14 @@ class Nameserver < ActiveRecord::Base self.ipv6 = Array(ipv6).reject(&:blank?).map(&:strip).map(&:upcase) end + def hostname_to_utf + self.hostname = SimpleIDN.to_unicode(hostname) + end + + def add_hostname_puny + self.hostname_puny = SimpleIDN.to_ascii(hostname) + end + def to_s hostname end diff --git a/db/migrate/20160429114732_add_puny_hostname_to_nameserver.rb b/db/migrate/20160429114732_add_puny_hostname_to_nameserver.rb new file mode 100644 index 000000000..368d9f144 --- /dev/null +++ b/db/migrate/20160429114732_add_puny_hostname_to_nameserver.rb @@ -0,0 +1,9 @@ +class AddPunyHostnameToNameserver < ActiveRecord::Migration + + def change + + add_column :nameservers, :hostname_puny, :string + execute "UPDATE nameservers n SET hostname_puny = n.hostname" + + end +end diff --git a/lib/tasks/convert.rake b/lib/tasks/convert.rake index 35e68046c..47e0ec7c2 100644 --- a/lib/tasks/convert.rake +++ b/lib/tasks/convert.rake @@ -71,5 +71,47 @@ namespace :convert do end end end + + desc 'Convert nameservers hostname and hostname_puny' + task nameserves_hostname: :environment do + + start = Time.zone.now.to_f + count = 0 + puts '-----> Converting hostnames...' + + Nameserver.find_each(:batch_size => 1000) do |ns| + ns.hostname = SimpleIDN.to_unicode(ns.hostname) + ns.hostname_puny = SimpleIDN.to_ascii(ns.hostname_puny) + ns.save validate: false + count += 1 + puts "-----> Converted #{count} nameservers" if count % 1000 == 0 + end + puts "-----> Converted #{count} nameservers #{(Time.zone.now.to_f - start).round(2)} seconds" + + end + + desc 'Convert nameservers history hostname' + task nameserves_history_hostname: :environment do + + start = Time.zone.now.to_f + count = 0 + puts '-----> Converting hostnames history...' + + NameserverVersion.find_each do |ns| + if obj = ns.object + obj["hostname"] = SimpleIDN.to_unicode(obj["hostname"]) + ns.object = obj + end + + if (obj_c = ns.object_changes).present? + obj_c["name"].map!{|e| e ? SimpleIDN.to_unicode(e) : e } if obj_c["hostname"] + ns.object_changes = obj_c + end + count += 1 + ns.save! + end + puts "-----> Converted #{count} history rows #{(Time.zone.now.to_f - start).round(2)} seconds" + end + end From 7bfbd0044fa9c81701ed93b06a7d9aa8fb1bca2b Mon Sep 17 00:00:00 2001 From: Stas Date: Thu, 12 May 2016 17:32:25 +0300 Subject: [PATCH 3/8] 114677695-validation_changes --- app/models/nameserver.rb | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb index d86813908..1dbb02d19 100644 --- a/app/models/nameserver.rb +++ b/app/models/nameserver.rb @@ -8,7 +8,7 @@ class Nameserver < ActiveRecord::Base # scope :owned_by_registrar, -> (registrar) { joins(:domain).where('domains.registrar_id = ?', registrar.id) } # rubocop: disable Metrics/LineLength - validates :hostname, domain_name: true + validates :hostname, format: { with: /\A(([a-zA-Z0-9]|[a-zA-ZäöüõÄÖÜÕ0-9][a-zA-ZäöüõÄÖÜÕ0-9\-]*[a-zA-ZäöüõÄÖÜÕ0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\z/ } # validates :ipv4, format: { with: /\A(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\z/, allow_blank: true } # validates :ipv6, format: { with: /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/, allow_blank: true } validate :val_ipv4 @@ -16,9 +16,7 @@ class Nameserver < ActiveRecord::Base # rubocop: enable Metrics/LineLength before_validation :normalize_attributes - before_validation :hostname_to_utf - after_validation :add_hostname_puny - + delegate :name, to: :domain, prefix: true def epp_code_map @@ -43,18 +41,15 @@ class Nameserver < ActiveRecord::Base self.ipv6 = Array(ipv6).reject(&:blank?).map(&:strip).map(&:upcase) end - def hostname_to_utf - self.hostname = SimpleIDN.to_unicode(hostname) - end - - def add_hostname_puny - self.hostname_puny = SimpleIDN.to_ascii(hostname) - end - def to_s hostname end + def hostname=(hostname) + self[:hostname] = SimpleIDN.to_unicode(hostname) + self[:hostname_puny] = SimpleIDN.to_ascii(hostname) + end + def val_ipv4 regexp = /\A(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\z/ ipv4.to_a.each do |ip| From b18021774d690e327b32fd12c5e2f95dd6329d8f Mon Sep 17 00:00:00 2001 From: Stas Date: Thu, 19 May 2016 13:35:01 +0300 Subject: [PATCH 4/8] 114677695-reg_exp_and_length_change --- app/models/nameserver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb index 1dbb02d19..729ac6cbf 100644 --- a/app/models/nameserver.rb +++ b/app/models/nameserver.rb @@ -8,7 +8,7 @@ class Nameserver < ActiveRecord::Base # scope :owned_by_registrar, -> (registrar) { joins(:domain).where('domains.registrar_id = ?', registrar.id) } # rubocop: disable Metrics/LineLength - validates :hostname, format: { with: /\A(([a-zA-Z0-9]|[a-zA-ZäöüõÄÖÜÕ0-9][a-zA-ZäöüõÄÖÜÕ0-9\-]*[a-zA-ZäöüõÄÖÜÕ0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\z/ } + validates :hostname, length: { maximum: 63 }, format: { with: /\A(([a-zA-Z0-9]|[a-zA-ZäöüõšžÄÖÜÕŠŽ0-9][a-zA-ZäöüõšžÄÖÜÕŠŽ0-9\-]*[a-zA-ZäöüõšžÄÖÜÕŠŽ0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\z/ } # validates :ipv4, format: { with: /\A(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\z/, allow_blank: true } # validates :ipv6, format: { with: /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/, allow_blank: true } validate :val_ipv4 From fa2231b27e30129f4719d5a1e4dabe0a7b857341 Mon Sep 17 00:00:00 2001 From: Stas Date: Tue, 24 May 2016 16:34:26 +0300 Subject: [PATCH 5/8] 114677695-additional_validation_rule --- app/models/nameserver.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb index 729ac6cbf..00a06c95f 100644 --- a/app/models/nameserver.rb +++ b/app/models/nameserver.rb @@ -16,6 +16,7 @@ class Nameserver < ActiveRecord::Base # rubocop: enable Metrics/LineLength before_validation :normalize_attributes + before_validation :check_puny_symbols delegate :name, to: :domain, prefix: true @@ -41,6 +42,11 @@ class Nameserver < ActiveRecord::Base self.ipv6 = Array(ipv6).reject(&:blank?).map(&:strip).map(&:upcase) end + def check_puny_symbols + regexp = /(\A|\.)..--/ + errors.add(:hostname, :invalid) if hostname =~ regexp + end + def to_s hostname end From 960eceb1f2feefc955b877225b25edc96cb1a743 Mon Sep 17 00:00:00 2001 From: Stas Date: Wed, 25 May 2016 13:21:35 +0300 Subject: [PATCH 6/8] 114677695-label_length_validation_changes --- app/models/nameserver.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb index 00a06c95f..4b6ef3df5 100644 --- a/app/models/nameserver.rb +++ b/app/models/nameserver.rb @@ -8,7 +8,7 @@ class Nameserver < ActiveRecord::Base # scope :owned_by_registrar, -> (registrar) { joins(:domain).where('domains.registrar_id = ?', registrar.id) } # rubocop: disable Metrics/LineLength - validates :hostname, length: { maximum: 63 }, format: { with: /\A(([a-zA-Z0-9]|[a-zA-ZäöüõšžÄÖÜÕŠŽ0-9][a-zA-ZäöüõšžÄÖÜÕŠŽ0-9\-]*[a-zA-ZäöüõšžÄÖÜÕŠŽ0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\z/ } + validates :hostname, format: { with: /\A(([a-zA-Z0-9]|[a-zA-ZäöüõšžÄÖÜÕŠŽ0-9][a-zA-ZäöüõšžÄÖÜÕŠŽ0-9\-]*[a-zA-ZäöüõšžÄÖÜÕŠŽ0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\z/ } # validates :ipv4, format: { with: /\A(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\z/, allow_blank: true } # validates :ipv6, format: { with: /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/, allow_blank: true } validate :val_ipv4 @@ -17,6 +17,7 @@ class Nameserver < ActiveRecord::Base before_validation :normalize_attributes before_validation :check_puny_symbols + before_validation :check_label_length delegate :name, to: :domain, prefix: true @@ -42,6 +43,12 @@ class Nameserver < ActiveRecord::Base self.ipv6 = Array(ipv6).reject(&:blank?).map(&:strip).map(&:upcase) end + def check_label_length + hostname.split('.').each do |label| + errors.add(:hostname, :invalid) if label.length > 63 + end + end + def check_puny_symbols regexp = /(\A|\.)..--/ errors.add(:hostname, :invalid) if hostname =~ regexp From f1a2f9e7f4d28e79dd7a86b0f094186d9a57caac Mon Sep 17 00:00:00 2001 From: Stas Date: Fri, 27 May 2016 12:56:47 +0300 Subject: [PATCH 7/8] 114677695-hostname_puny_validation --- app/models/nameserver.rb | 5 +++-- config/locales/en.yml | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb index 4b6ef3df5..ee6684d12 100644 --- a/app/models/nameserver.rb +++ b/app/models/nameserver.rb @@ -28,6 +28,7 @@ class Nameserver < ActiveRecord::Base ], '2005' => [ [:hostname, :invalid, { value: { obj: 'hostAttr', val: hostname } }], + [:hostname_puny, :puny_to_long, { value: { obj: 'hostAttr', val: hostname } }], [:ipv4, :invalid, { value: { obj: 'hostAddr', val: ipv4 } }], [:ipv6, :invalid, { value: { obj: 'hostAddr', val: ipv6 } }] ], @@ -44,8 +45,8 @@ class Nameserver < ActiveRecord::Base end def check_label_length - hostname.split('.').each do |label| - errors.add(:hostname, :invalid) if label.length > 63 + hostname_puny.split('.').each do |label| + errors.add(:hostname_puny, :puny_to_long) if label.length > 63 end end diff --git a/config/locales/en.yml b/config/locales/en.yml index de5891c77..b90f62bc0 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -131,6 +131,8 @@ en: hostname: invalid: 'Hostname is invalid' taken: 'Nameserver already exists on this domain' + hostname_puny: + puny_to_long: 'Hostname puny is too long (maximum is 63 characters)' ipv4: blank: 'IPv4 is missing' invalid: 'IPv4 is invalid' From 684b8bf0d9db8ea795470d906fe3cecb734bf78d Mon Sep 17 00:00:00 2001 From: Stas Date: Fri, 27 May 2016 16:43:23 +0300 Subject: [PATCH 8/8] 114677695-error_text_change --- app/models/nameserver.rb | 4 ++-- config/locales/en.yml | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb index ee6684d12..9ca1bebf7 100644 --- a/app/models/nameserver.rb +++ b/app/models/nameserver.rb @@ -28,7 +28,7 @@ class Nameserver < ActiveRecord::Base ], '2005' => [ [:hostname, :invalid, { value: { obj: 'hostAttr', val: hostname } }], - [:hostname_puny, :puny_to_long, { value: { obj: 'hostAttr', val: hostname } }], + [:hostname, :puny_to_long, { value: { obj: 'hostAttr', val: hostname } }], [:ipv4, :invalid, { value: { obj: 'hostAddr', val: ipv4 } }], [:ipv6, :invalid, { value: { obj: 'hostAddr', val: ipv6 } }] ], @@ -46,7 +46,7 @@ class Nameserver < ActiveRecord::Base def check_label_length hostname_puny.split('.').each do |label| - errors.add(:hostname_puny, :puny_to_long) if label.length > 63 + errors.add(:hostname, :puny_to_long) if label.length > 63 end end diff --git a/config/locales/en.yml b/config/locales/en.yml index b90f62bc0..e01451d60 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -131,8 +131,7 @@ en: hostname: invalid: 'Hostname is invalid' taken: 'Nameserver already exists on this domain' - hostname_puny: - puny_to_long: 'Hostname puny is too long (maximum is 63 characters)' + puny_to_long: 'Hostname puny label is too long (maximum is 63 characters)' ipv4: blank: 'IPv4 is missing' invalid: 'IPv4 is invalid'