From ac4b63f390da8d0517044e6a6d1e748192cdfd54 Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Fri, 21 Nov 2014 15:30:40 +0200 Subject: [PATCH 01/13] Add zonefile generation procedure --- Gemfile | 3 + Gemfile.lock | 3 + app/controllers/admin/domains_controller.rb | 5 - .../admin/zonefile_settings_controller.rb | 30 ++++ app/controllers/admin/zonefiles_controller.rb | 41 +---- app/models/country.rb | 6 + app/models/domain.rb | 29 ---- app/models/zonefile.rb | 3 + app/models/zonefile_setting.rb | 7 + app/validators/domain_name_validator.rb | 1 + app/views/admin/settings/index.haml | 2 +- app/views/admin/zonefile_settings/edit.haml | 50 ++++++ app/views/admin/zonefile_settings/index.haml | 20 +++ app/views/layouts/application.haml | 2 +- config/application.rb | 2 - config/locales/en.yml | 38 +++-- config/routes.rb | 8 +- .../20141120110330_create_zonefile_setting.rb | 28 ++++ .../20141120140837_add_ee_domain_objects.rb | 58 +++++++ .../20141121093125_add_zonefile_procedure.rb | 109 ++++++++++++ db/schema.rb | 14 +- db/seeds.rb | 9 + lib/zonefile.rb | 157 ------------------ 23 files changed, 370 insertions(+), 255 deletions(-) create mode 100644 app/controllers/admin/zonefile_settings_controller.rb create mode 100644 app/models/zonefile.rb create mode 100644 app/models/zonefile_setting.rb create mode 100644 app/views/admin/zonefile_settings/edit.haml create mode 100644 app/views/admin/zonefile_settings/index.haml create mode 100644 db/migrate/20141120110330_create_zonefile_setting.rb create mode 100644 db/migrate/20141120140837_add_ee_domain_objects.rb create mode 100644 db/migrate/20141121093125_add_zonefile_procedure.rb delete mode 100644 lib/zonefile.rb diff --git a/Gemfile b/Gemfile index c3724a18a..22f8bcaa6 100644 --- a/Gemfile +++ b/Gemfile @@ -80,6 +80,9 @@ gem 'delayed_job_active_record', '~> 4.0.2' gem 'daemons' group :development, :test do + # for inserting dummy data + gem 'activerecord-import', '~> 0.6.0' + gem 'capybara', '~> 2.4.1' # For feature testing # gem 'capybara-webkit', '1.2.0' # Webkit driver didn't work with turbolinks diff --git a/Gemfile.lock b/Gemfile.lock index 356435bbc..889befd31 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -21,6 +21,8 @@ GEM activemodel (= 4.1.4) activesupport (= 4.1.4) arel (~> 5.0.0) + activerecord-import (0.6.0) + activerecord (>= 3.0) activesupport (4.1.4) i18n (~> 0.6, >= 0.6.9) json (~> 1.7, >= 1.7.7) @@ -361,6 +363,7 @@ PLATFORMS ruby DEPENDENCIES + activerecord-import (~> 0.6.0) bootstrap-sass (~> 3.2.0.1) brakeman (~> 2.6.2) bullet (~> 4.14.0) diff --git a/app/controllers/admin/domains_controller.rb b/app/controllers/admin/domains_controller.rb index c12492edb..f0bbd3abf 100644 --- a/app/controllers/admin/domains_controller.rb +++ b/app/controllers/admin/domains_controller.rb @@ -27,11 +27,6 @@ class Admin::DomainsController < AdminController end end - def zonefile - @zonefile = @domain.generate_zonefile - # send_data @zonefile, filename: 'bla.txt' - end - private def set_domain diff --git a/app/controllers/admin/zonefile_settings_controller.rb b/app/controllers/admin/zonefile_settings_controller.rb new file mode 100644 index 000000000..da4c8a557 --- /dev/null +++ b/app/controllers/admin/zonefile_settings_controller.rb @@ -0,0 +1,30 @@ +class Admin::ZonefileSettingsController < ApplicationController + before_action :set_zonefile_setting, only: [:update, :edit] + def index + @zonefile_settings = ZonefileSetting.all + end + + def edit + @zonefile_setting = ZonefileSetting.find(params[:id]) + end + + def update + if @zonefile_setting.update(zonefile_setting_params) + flash[:notice] = I18n.t('shared.record_updated') + redirect_to admin_zonefile_settings_path + else + flash.now[:alert] = I18n.t('shared.failed_to_update_record') + render 'edit' + end + end + + private + + def set_zonefile_setting + @zonefile_setting = ZonefileSetting.find(params[:id]) + end + + def zonefile_setting_params + params.require(:zonefile_setting).permit(:ttl, :refresh, :retry, :expire, :minimum_ttl, :email) + end +end diff --git a/app/controllers/admin/zonefiles_controller.rb b/app/controllers/admin/zonefiles_controller.rb index 564928de4..811df5627 100644 --- a/app/controllers/admin/zonefiles_controller.rb +++ b/app/controllers/admin/zonefiles_controller.rb @@ -2,44 +2,7 @@ class Admin::ZonefilesController < ApplicationController # TODO: Refactor this # rubocop:disable Metrics/MethodLength def index - zf = Zonefile.new - - zf.origin = 'ee.' - zf.ttl = '43200' - - zf.soa[:primary_ns] = 'ns.tld.ee.' - zf.soa[:email] = 'hostmaster.eestiinternet.ee.' - zf.soa[:origin] = 'ee.' - zf.soa[:refresh] = '3600' - zf.soa[:retry] = '900' - zf.soa[:expire] = '1209600' - zf.soa[:minimumTTL] = '3600' - zf.new_serial - - zf.ns << { name: 'ee.', class: 'IN', host: 'b.tld.ee.' } - zf.ns << { name: 'ee.', class: 'IN', host: 'e.tld.ee.' } - zf.ns << { name: 'ee.', class: 'IN', host: 'ee.aso.ee.' } - zf.ns << { name: 'ee.', class: 'IN', host: 'ns.ut.ee.' } - zf.ns << { name: 'ee.', class: 'IN', host: 'ns.tld.ee.' } - zf.ns << { name: 'ee.', class: 'IN', host: 'sunic.sunet.se.' } - - zf.a << { name: 'b.tld.ee.', class: 'IN', host: '194.146.106.110' } - zf.a4 << { name: 'b.tld.ee.', class: 'IN', host: '2001:67c:1010:28::53' } - zf.a << { name: 'e.tld.ee.', class: 'IN', host: '204.61.216.36' } - zf.a4 << { name: 'e.tld.ee.', class: 'IN', host: '2001:678:94:53::53' } - zf.a << { name: 'ee.aso.ee.', class: 'IN', host: '213.184.51.122' } - zf.a4 << { name: 'ee.aso.ee.', class: 'IN', host: '2a02:88:0:21::2' } - zf.a << { name: 'ns.ut.ee.', class: 'IN', host: '193.40.5.99' } - zf.a << { name: 'ns.tld.ee.', class: 'IN', host: '195.43.87.10' } - zf.a << { name: 'sunic.sunet.se.', class: 'IN', host: '192.36.125.2' } - zf.a4 << { name: 'sunic.sunet.se.', class: 'IN', host: '2001:6b0:7::2' } - - Nameserver.all.includes(:domain).each do |x| - zf.ns << { name: "#{x.domain_name}.", class: 'IN', host: "#{x.hostname}." } - zf.a << { name: "#{x.hostname}.", class: 'IN', host: x.ipv4 } if x.ipv4.present? - zf.a4 << { name: "#{x.hostname}.", class: 'IN', host: x.ipv6 } if x.ipv6.present? - end - - @zonefile = zf.generate + @zonefile = ActiveRecord::Base.connection.execute("select generate_zonefile('ee')")[0]['generate_zonefile'] + send_data @zonefile, filename: 'zonefile-1000.txt' end end diff --git a/app/models/country.rb b/app/models/country.rb index 1e26c58a3..d4e8698bf 100644 --- a/app/models/country.rb +++ b/app/models/country.rb @@ -2,4 +2,10 @@ class Country < ActiveRecord::Base def to_s name end + + class << self + def estonia + find_by(iso: 'EE') + end + end end diff --git a/app/models/domain.rb b/app/models/domain.rb index 22ecdc4c7..7d8dca50e 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -301,35 +301,6 @@ class Domain < ActiveRecord::Base end end - def generate_zonefile - zf = Zonefile.new - zf.ttl = '3600' - zf.origin = "#{name}." - ns = nameservers.first - zf.soa[:primary_ns] = "#{ns.hostname}." - zf.soa[:email] = 'hostmaster.internet.ee' - zf.soa[:origin] = "#{name}." - zf.soa[:refresh] = '10800' - zf.soa[:retry] = '3600' - zf.soa[:expire] = '604800' - zf.soa[:minimumTTL] = '3600' - - nameservers.each do |x| - zf.ns << { name: "#{name}.", class: 'IN', host: "#{x.hostname}." } - end - - dnskeys.each do |x| - zf.ds << { name: "#{name}.", ttl: '86400', class: 'IN', key_tag: x.ds_key_tag, algorithm: x.ds_alg, - digest_type: x.ds_digest_type, digest: x.ds_digest } - - zf.dnskey << { name: "#{name}.", ttl: '86400', class: 'IN', flag: x.flags, - protocol: x.protocol, algorithm: x.alg, public_key: x.public_key } - end - - zf.new_serial - zf.generate - end - class << self def convert_period_to_time(period, unit) return period.to_i.days if unit == 'd' diff --git a/app/models/zonefile.rb b/app/models/zonefile.rb new file mode 100644 index 000000000..5e42b165a --- /dev/null +++ b/app/models/zonefile.rb @@ -0,0 +1,3 @@ +class Zonefile < ActiveRecord::Base + +end diff --git a/app/models/zonefile_setting.rb b/app/models/zonefile_setting.rb new file mode 100644 index 000000000..d6e334a36 --- /dev/null +++ b/app/models/zonefile_setting.rb @@ -0,0 +1,7 @@ +class ZonefileSetting < ActiveRecord::Base + validates :origin, :ttl, :refresh, :retry, :expire, :minimum_ttl, :email, presence: true + validates :ttl, :refresh, :retry, :expire, :minimum_ttl, numericality: { only_integer: true } + def to_s + origin + end +end diff --git a/app/validators/domain_name_validator.rb b/app/validators/domain_name_validator.rb index 19cd5a17b..4d337b8b5 100644 --- a/app/validators/domain_name_validator.rb +++ b/app/validators/domain_name_validator.rb @@ -16,6 +16,7 @@ class DomainNameValidator < ActiveModel::EachValidator class << self def validate_format(value) + return true if value == 'ee' return true unless value value = value.mb_chars.downcase.strip diff --git a/app/views/admin/settings/index.haml b/app/views/admin/settings/index.haml index d3339c382..c3c4b7254 100644 --- a/app/views/admin/settings/index.haml +++ b/app/views/admin/settings/index.haml @@ -14,7 +14,7 @@ %tbody - @settings.each do |x| %tr - %td= t("shared.#{x.var}") + %td= t("#{x.var}") - if [TrueClass, FalseClass].include?(x.value.class) %td = hidden_field_tag("[settings][#{x.var}]", '') diff --git a/app/views/admin/zonefile_settings/edit.haml b/app/views/admin/zonefile_settings/edit.haml new file mode 100644 index 000000000..fb51aae04 --- /dev/null +++ b/app/views/admin/zonefile_settings/edit.haml @@ -0,0 +1,50 @@ +%h2= t('zonefile_settings') +%hr += form_for [:admin, @zonefile_setting], html: { class: 'form-horizontal' } do |f| + .row + .col-md-12 + #domain-statuses + .errors + - if f.object.errors.any? + - f.object.errors.full_messages.each do |x| + = x + %br + - if f.object.errors.any? + %hr + .form-group + = f.label :origin, class: 'col-md-2 control-label' + .col-md-10 + = f.text_field :origin, class: 'form-control', disabled: true + + .form-group + = f.label :ttl, class: 'col-md-2 control-label' + .col-md-10 + = f.text_field :ttl, class: 'form-control' + + .form-group + = f.label :refresh, class: 'col-md-2 control-label' + .col-md-10 + = f.text_field :refresh, class: 'form-control' + + .form-group + = f.label :retry, class: 'col-md-2 control-label' + .col-md-10 + = f.text_field :retry, class: 'form-control' + .form-group + = f.label :expire, class: 'col-md-2 control-label' + .col-md-10 + = f.text_field :expire, class: 'form-control' + + .form-group + = f.label :minimum_ttl, class: 'col-md-2 control-label' + .col-md-10 + = f.text_field :minimum_ttl, class: 'form-control' + + .form-group + = f.label :email, class: 'col-md-2 control-label' + .col-md-10 + = f.text_field :email, class: 'form-control' + + .row + .col-md-12.text-right + %button.btn.btn-primary=t('shared.save') diff --git a/app/views/admin/zonefile_settings/index.haml b/app/views/admin/zonefile_settings/index.haml new file mode 100644 index 000000000..6e3a7ae17 --- /dev/null +++ b/app/views/admin/zonefile_settings/index.haml @@ -0,0 +1,20 @@ +.row + .col-sm-12 + %h2.text-center-xs= t('zonefile_settings') +%hr +.row + .col-md-12 + .table-responsive + %table.table.table-hover.table-bordered.table-condensed + %thead + %tr + %th{class: 'col-xs-10'} + = t('origin') + %th{class: 'col-xs-2'} + = t('action') + %tbody + - @zonefile_settings.each do |x| + %tr + %td= link_to(x, edit_admin_zonefile_setting_path(x)) + %td + = link_to(t('generate_zonefile'), admin_zonefiles_path, class: 'btn btn-xs btn-primary') diff --git a/app/views/layouts/application.haml b/app/views/layouts/application.haml index bc449fa96..f4883ee10 100644 --- a/app/views/layouts/application.haml +++ b/app/views/layouts/application.haml @@ -38,7 +38,7 @@ %li = link_to t('shared.settings'), admin_settings_path %li - = link_to t('zonefile'), admin_zonefiles_path + = link_to t('zonefile'), admin_zonefile_settings_path %li.divider %li.dropdown-header= t('shared.users') %li diff --git a/config/application.rb b/config/application.rb index f119c2ebd..8e4a6a7c2 100644 --- a/config/application.rb +++ b/config/application.rb @@ -27,8 +27,6 @@ module Registry # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] # config.i18n.default_locale = :de - config.autoload_paths += %W(#{config.root}/lib) - config.generators do |g| g.stylesheets false g.javascripts false diff --git a/config/locales/en.yml b/config/locales/en.yml index 41f08825b..b4e8d1538 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -201,13 +201,6 @@ en: taken: 'Public key already exists' blank: 'Public key is missing' - - delegation_signer: - attributes: - dnskeys: - out_of_range: 'DNS keys count must be between %{min}-%{max}' - - attributes: epp_domain: &epp_domain_attributes name: 'Domain name' @@ -223,6 +216,13 @@ en: alg: 'Algorithm' public_key: 'Public key' + zonefile_setting: + ttl: 'TTL' + refresh: 'Refresh' + retry: 'Retry' + expire: 'Expire' + minimum_ttl: 'Minimum ttl' + email: 'E-Mail' errors: messages: @@ -410,14 +410,6 @@ en: authentication_error: 'Authentication error' ds_data_and_key_data_must_not_exists_together: 'dsData and keyData objects must not exists together' - ns_min_count: 'Nameserver minimum count' - ns_max_count: 'Nameserver maximum count' - dnskeys_min_count: 'DNS keys minimum count' - dnskeys_max_count: 'DNS keys maximum count' - ds_data_allowed: 'DS data allowed' - ds_data_with_key_allowed: 'Allow DS data with key' - key_data_allowed: 'Allow key data' - ds_algorithm: 'DS algorithm' setting: 'Setting' registrar: 'Registrar' @@ -428,3 +420,19 @@ en: zonefile: 'Zonefile' only_one_parameter_allowed: 'Only one parameter allowed: %{param_1} or %{param_2}' required_parameter_missing_choice: 'Required parameter missing: %{param_1} or %{param_2}' + zonefile_ttl: 'Zonefile TTL' + zonefile_refresh: 'Zonefile refresh' + zonefile_retry: 'Zonefile retry' + zonefile_expire: 'Zonefile expire' + zonefile_minimum_ttl: 'Zonefile minimum TTL' + zonefile_email: 'Zonefile e-mail' + transfer_wait_time: 'Transfer wait time' + ns_min_count: 'Nameserver minimum count' + ns_max_count: 'Nameserver maximum count' + dnskeys_min_count: 'DNS keys minimum count' + dnskeys_max_count: 'DNS keys maximum count' + ds_data_allowed: 'DS data allowed' + ds_data_with_key_allowed: 'Allow DS data with key' + key_data_allowed: 'Allow key data' + ds_algorithm: 'DS algorithm' + zonefile_settings: 'Zonefile settings' diff --git a/config/routes.rb b/config/routes.rb index 737d5eac4..82dc72ae1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,11 +9,9 @@ Rails.application.routes.draw do namespace(:admin) do resources :zonefiles - resources :domains do - member do - get 'zonefile' - end - end + resources :zonefile_settings + + resources :domains resources :settings resources :registrars do collection do diff --git a/db/migrate/20141120110330_create_zonefile_setting.rb b/db/migrate/20141120110330_create_zonefile_setting.rb new file mode 100644 index 000000000..b91320051 --- /dev/null +++ b/db/migrate/20141120110330_create_zonefile_setting.rb @@ -0,0 +1,28 @@ +class CreateZonefileSetting < ActiveRecord::Migration + def change + create_table :zonefile_settings do |t| + t.string :origin + t.integer :ttl + t.integer :refresh + t.integer :retry + t.integer :expire + t.integer :minimum_ttl + t.string :email + + t.timestamps + end + + # rubocop: disable Style/NumericLiterals + ZonefileSetting.create({ + origin: 'ee', + ttl: 43200, + refresh: 3600, + retry: 900, + expire: 1209600, + minimum_ttl: 3600, + email: 'hostmaster.eestiinternet.ee' + }) + end +end + + diff --git a/db/migrate/20141120140837_add_ee_domain_objects.rb b/db/migrate/20141120140837_add_ee_domain_objects.rb new file mode 100644 index 000000000..ab00f7b07 --- /dev/null +++ b/db/migrate/20141120140837_add_ee_domain_objects.rb @@ -0,0 +1,58 @@ +class AddEeDomainObjects < ActiveRecord::Migration + # rubocop:disable Metrics/MethodLength + def up + r = Registrar.create( + name: 'EIS', + reg_no: '123321', + address: 'Tallinn', + country: Country.estonia + ) + + c = Contact.create( + name: 'EIS', + phone: '+372.123321', + email: 'info@testing.ee', + ident: '123321', + ident_type: 'ico', + address: Address.create( + city: 'Tallinn', + country: Country.estonia + ), + registrar: r + ) + + EppUser.create( + registrar: r, + username: 'testeis', + password: 'testeis', + active: true + ) + + Domain.create( + name: 'ee', + valid_to: Date.new(9999, 1, 1), + period: 1, + period_unit: 'y', + owner_contact: c, + nameservers: [ + Nameserver.create(hostname: 'ns.tld.ee', ipv4: '195.43.87.10'), + Nameserver.create(hostname: 'b.tld.ee', ipv4: '194.146.106.110', ipv6: '2001:67c:1010:28::53'), + Nameserver.create(hostname: 'e.tld.ee', ipv4: '204.61.216.36', ipv6: '2001:678:94:53::53'), + Nameserver.create(hostname: 'ee.aso.ee', ipv4: '213.184.51.122', ipv6: '2a02:88:0:21::2'), + Nameserver.create(hostname: 'ns.ut.ee', ipv4: '193.40.5.99', ipv6: ''), + Nameserver.create(hostname: 'sunic.sunet.se', ipv4: '195.80.103.202') + ], + admin_contacts: [c], + registrar: r + ) + end + # rubocop:enable Metrics/MethodLength + + def down + Domain.find_by(name: 'ee').destroy + EppUser.find_by(username: 'testeis').destroy + Contact.find_by(name: 'EIS').destroy + Registrar.find_by(name: 'EIS').destroy + + end +end diff --git a/db/migrate/20141121093125_add_zonefile_procedure.rb b/db/migrate/20141121093125_add_zonefile_procedure.rb new file mode 100644 index 000000000..cd92bc635 --- /dev/null +++ b/db/migrate/20141121093125_add_zonefile_procedure.rb @@ -0,0 +1,109 @@ +class AddZonefileProcedure < ActiveRecord::Migration + # rubocop:disable Metrics/MethodLength + def up + execute <<-SQL + CREATE OR REPLACE FUNCTION generate_zonefile(i_origin varchar) + RETURNS text AS $$ + DECLARE + zone_header text := concat('$ORIGIN ', i_origin, '.'); + tmp text := ''; + ns_records text := ''; + a_records text := ''; + a4_records text := ''; + ds_records text := ''; + BEGIN + -- zonefile header + SELECT concat( + format('%-10s', '$ORIGIN'), i_origin, '.', chr(10), + format('%-10s', '$TTL'), zf.ttl, chr(10), chr(10), + format('%-10s', i_origin || '.'), 'IN SOA ', 'ns.tld.ee', '. ', zf.email, '. (', chr(10), + format('%-17s', ''), format('%-12s', '2014111210'), '; serial number', chr(10), + format('%-17s', ''), format('%-12s', zf.refresh), '; refresh, seconds', chr(10), + format('%-17s', ''), format('%-12s', zf.retry), '; retry, seconds', chr(10), + format('%-17s', ''), format('%-12s', zf.expire), '; expire, seconds', chr(10), + format('%-17s', ''), format('%-12s', zf.minimum_ttl), '; minimum TTL, seconds', chr(10), + format('%-17s', ''), ')' + ) FROM zonefile_settings zf WHERE i_origin = zf.origin INTO zone_header; + + -- ns records + SELECT array_to_string( + array( + SELECT concat(d.name, '. IN NS ', ns.hostname, '.') + FROM domains d + JOIN nameservers ns ON ns.domain_id = d.id + WHERE d.name LIKE '%' || i_origin + ORDER BY + CASE d.name + WHEN i_origin THEN 1 + END + ), + chr(10) + ) INTO ns_records; + + -- a records + SELECT array_to_string( + array( + SELECT concat(ns.hostname, '. IN A ', ns.ipv4, '.') + FROM domains d + JOIN nameservers ns ON ns.domain_id = d.id + WHERE d.name LIKE '%' || i_origin AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> '' + ORDER BY + CASE d.name + WHEN i_origin THEN 1 + END + ), + chr(10) + ) INTO a_records; + + -- aaaa records + SELECT array_to_string( + array( + SELECT concat(ns.hostname, '. IN AAAA ', ns.ipv6, '.') + FROM domains d + JOIN nameservers ns ON ns.domain_id = d.id + WHERE d.name LIKE '%' || i_origin AND ns.ipv6 IS NOT NULL AND ns.ipv6 <> '' + ORDER BY + CASE d.name + WHEN i_origin THEN 1 + END + ), + chr(10) + ) INTO a4_records; + + -- ds records + SELECT array_to_string( + array( + SELECT concat( + d.name, '. 86400 IN ', dk.ds_key_tag, ' ', + dk.ds_alg, ' ', dk.ds_digest_type, ' ', dk.ds_digest + ) + FROM domains d + JOIN dnskeys dk ON dk.domain_id = d.id + WHERE d.name LIKE '%' || i_origin + ORDER BY + CASE d.name + WHEN i_origin THEN 1 + END + ), + chr(10) + ) INTO ds_records; + + RETURN concat( + zone_header, chr(10), chr(10), + '; Zone NS Records', chr(10), ns_records, chr(10), chr(10), + '; Zone A Records', chr(10), a_records, chr(10), chr(10), + '; Zone AAAA Records', chr(10), a4_records, chr(10), chr(10), + '; Zone DS Records', chr(10), ds_records + ); + END; + $$ + LANGUAGE plpgsql; + SQL + end + + def down + execute <<-SQL + DROP FUNCTION generate_zonefile(i_origin varchar); + SQL + end +end diff --git a/db/schema.rb b/db/schema.rb index 295d7b948..39a8d94f8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20141114130737) do +ActiveRecord::Schema.define(version: 20141121093125) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -335,4 +335,16 @@ ActiveRecord::Schema.define(version: 20141114130737) do add_index "versions", ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id", using: :btree + create_table "zonefile_settings", force: true do |t| + t.string "origin" + t.integer "ttl" + t.integer "refresh" + t.integer "retry" + t.integer "expire" + t.integer "minimum_ttl" + t.string "email" + t.datetime "created_at" + t.datetime "updated_at" + end + end diff --git a/db/seeds.rb b/db/seeds.rb index 8769d15bc..24d16ffb2 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -78,4 +78,13 @@ Setting.ns_max_count = 11 Setting.transfer_wait_time = 0 +# rubocop: disable Style/NumericLiterals +Setting.zonefile_ttl = 43200 +Setting.zonefile_refresh = 3600 +Setting.zonefile_retry = 900 +Setting.zonefile_expire = 1209600 +Setting.zonefile_minimum_ttl = 3600 +Setting.zonefile_email = 'hostmaster.eestiinternet.ee' +# rubocop: enable Style/NumericLiterals + # Setting.whois_enabled = true only uncomment this if you wish whois diff --git a/lib/zonefile.rb b/lib/zonefile.rb deleted file mode 100644 index dfcad1a6a..000000000 --- a/lib/zonefile.rb +++ /dev/null @@ -1,157 +0,0 @@ -class Zonefile - RECORDS = [:mx, :a, :a4, :ns, :cname, :txt, :ptr, :srv, :soa, :ds, - :dnskey, :rrsig, :nsec, :nsec3, :nsec3param, :tlsa, :naptr] - - attr_accessor(*RECORDS, :ttl, :origin) - - def initialize(obj = {}) - RECORDS.each do |x| - if x == :soa - send("#{x}=", {}) - else - send("#{x}=", []) - end - end - - obj.each do |k, v| - send("#{k}=", v) - end - end - - def new_serial - base = sprintf('%04d%02d%02d', Time.now.year, Time.now.month, Time.now.day) - - if soa[:serial] - if base == soa[:serial].first(8) - sequence = soa[:serial].last(2).to_i + 1 - soa[:serial] = "#{base}#{sprintf('%02d', sequence)}" - return soa[:serial] - end - end - - soa[:serial] = soa[:serial] = "#{base}00" - end - - # rubocop:disable Metrics/MethodLength - # rubocop: disable Metrics/PerceivedComplexity - # rubocop: disable Metrics/CyclomaticComplexity - def generate - out = <<-eos -$ORIGIN #{origin} ; designates the start of this zone file in the namespace -$TTL #{ttl} ; default expiration time of all resource records without their own TTL value - -#{soa[:origin]} #{soa[:ttl]} IN SOA #{soa[:primary_ns]} #{soa[:email]} ( - #{sprintf('%-13s', soa[:serial])}; serial number - #{sprintf('%-13s', soa[:refresh])}; refresh, seconds - #{sprintf('%-13s', soa[:retry])}; retry, seconds - #{sprintf('%-13s', soa[:expire])}; expire, seconds - #{sprintf('%-13s', soa[:minimumTTL])}; minimum TTL, seconds - ) - eos - - ns.each do |ns| - out << "#{ns[:name]} #{ns[:ttl]} #{ns[:class]} NS #{ns[:host]}\n" - end - - out << "\n; Zone MX Records\n" unless mx.empty? - - mx.each do |mx| - out << "#{mx[:name]} #{mx[:ttl]} #{mx[:class]} MX #{mx[:pri]} #{mx[:host]}\n" - end - - out << "\n; Zone A Records\n" unless a.empty? - - a.each do |a| - out << "#{a[:name]} #{a[:ttl]} #{a[:class]} A #{a[:host]}\n" - end - - out << "\n; Zone CNAME Records\n" unless cname.empty? - - cname.each do |cn| - out << "#{cn[:name]} #{cn[:ttl]} #{cn[:class]} CNAME #{cn[:host]}\n" - end - - out << "\n; Zone AAAA Records\n" unless a4.empty? - - a4.each do |a4| - out << "#{a4[:name]} #{a4[:ttl]} #{a4[:class]} AAAA #{a4[:host]}\n" - end - - out << "\n; Zone TXT Records\n" unless txt.empty? - - txt.each do |tx| - out << "#{tx[:name]} #{tx[:ttl]} #{tx[:class]} TXT #{tx[:text]}\n" - end - - out << "\n; Zone SRV Records\n" unless srv.empty? - - srv.each do |srv| - out << "#{srv[:name]} #{srv[:ttl]} #{srv[:class]} SRV #{srv[:pri]} "\ - "#{srv[:weight]} #{srv[:port]} #{srv[:host]}\n" - end - - out << "\n; Zone PTR Records\n" unless ptr.empty? - - ptr.each do |ptr| - out << "#{ptr[:name]} #{ptr[:ttl]} #{ptr[:class]} PTR #{ptr[:host]}\n" - end - - out << "\n; Zone DS Records\n" unless ds.empty? - - ds.each do |ds| - out << "#{ds[:name]} #{ds[:ttl]} #{ds[:class]} DS #{ds[:key_tag]} #{ds[:algorithm]} "\ - "#{ds[:digest_type]} #{ds[:digest]}\n" - end - - out << "\n; Zone NSEC Records\n" unless self.ds.empty? - - nsec.each do |nsec| - out << "#{nsec[:name]} #{nsec[:ttl]} #{nsec[:class]} NSEC #{nsec[:next]} #{nsec[:types]}\n" - end - - out << "\n; Zone NSEC3 Records\n" unless self.ds.empty? - - nsec3.each do |nsec3| - out << "#{nsec3[:name]} #{nsec3[:ttl]} #{nsec3[:class]} NSEC3 #{nsec3[:algorithm]} "\ - "#{nsec3[:flags]} #{nsec3[:iterations]} #{nsec3[:salt]} #{nsec3[:next]} #{nsec3[:types]}\n" - end - - out << "\n; Zone NSEC3PARAM Records\n" unless self.ds.empty? - - nsec3param.each do |nsec3param| - out << "#{nsec3param[:name]} #{nsec3param[:ttl]} #{nsec3param[:class]} NSEC3PARAM "\ - "#{nsec3param[:algorithm]} #{nsec3param[:flags]} #{nsec3param[:iterations]} #{nsec3param[:salt]}\n" - end - - out << "\n; Zone DNSKEY Records\n" unless self.ds.empty? - - dnskey.each do |dnskey| - out << "#{dnskey[:name]} #{dnskey[:ttl]} #{dnskey[:class]} DNSKEY #{dnskey[:flag]} "\ - "#{dnskey[:protocol]} #{dnskey[:algorithm]} #{dnskey[:public_key]}\n" - end - - out << "\n; Zone RRSIG Records\n" unless self.ds.empty? - - rrsig.each do |rrsig| - out << "#{rrsig[:name]} #{rrsig[:ttl]} #{rrsig[:class]} RRSIG #{rrsig[:type_covered]} "\ - "#{rrsig[:algorithm]} #{rrsig[:labels]} #{rrsig[:original_ttl]} #{rrsig[:expiration]} "\ - "#{rrsig[:inception]} #{rrsig[:key_tag]} #{rrsig[:signer]} #{rrsig[:signature]}\n" - end - - out << "\n; Zone TLSA Records\n" unless tlsa.empty? - - tlsa.each do |tlsa| - out << "#{tlsa[:name]} #{tlsa[:ttl]} #{tlsa[:class]} TLSA #{tlsa[:certificate_usage]} "\ - "#{tlsa[:selector]} #{tlsa[:matching_type]} #{tlsa[:data]}\n" - end - - out << "\n; Zone NAPTR Records\n" unless self.ds.empty? - - naptr.each do |naptr| - out << "#{naptr[:name]} #{naptr[:ttl]} #{naptr[:class]} NAPTR #{naptr[:order]} "\ - "#{naptr[:preference]} #{naptr[:flags]} #{naptr[:service]} #{naptr[:regexp]} #{naptr[:replacement]}\n" - end - - out - end -end From 4caa0ef9030556a24a94cde393c81aa535d46809 Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Fri, 21 Nov 2014 19:16:22 +0200 Subject: [PATCH 02/13] Refactor, spacing in zone file --- app/models/zonefile.rb | 3 --- config/locales/en.yml | 8 +------- .../20141120110330_create_zonefile_setting.rb | 15 +++++++++++++- .../20141120140837_add_ee_domain_objects.rb | 14 ++++++++++++- .../20141121093125_add_zonefile_procedure.rb | 20 +++++++++++++++---- db/schema.rb | 14 +------------ db/seeds.rb | 9 --------- 7 files changed, 45 insertions(+), 38 deletions(-) delete mode 100644 app/models/zonefile.rb diff --git a/app/models/zonefile.rb b/app/models/zonefile.rb deleted file mode 100644 index 5e42b165a..000000000 --- a/app/models/zonefile.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Zonefile < ActiveRecord::Base - -end diff --git a/config/locales/en.yml b/config/locales/en.yml index b4e8d1538..79317856a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -221,7 +221,7 @@ en: refresh: 'Refresh' retry: 'Retry' expire: 'Expire' - minimum_ttl: 'Minimum ttl' + minimum_ttl: 'Minimum TTL' email: 'E-Mail' errors: @@ -420,12 +420,6 @@ en: zonefile: 'Zonefile' only_one_parameter_allowed: 'Only one parameter allowed: %{param_1} or %{param_2}' required_parameter_missing_choice: 'Required parameter missing: %{param_1} or %{param_2}' - zonefile_ttl: 'Zonefile TTL' - zonefile_refresh: 'Zonefile refresh' - zonefile_retry: 'Zonefile retry' - zonefile_expire: 'Zonefile expire' - zonefile_minimum_ttl: 'Zonefile minimum TTL' - zonefile_email: 'Zonefile e-mail' transfer_wait_time: 'Transfer wait time' ns_min_count: 'Nameserver minimum count' ns_max_count: 'Nameserver maximum count' diff --git a/db/migrate/20141120110330_create_zonefile_setting.rb b/db/migrate/20141120110330_create_zonefile_setting.rb index b91320051..fdba51948 100644 --- a/db/migrate/20141120110330_create_zonefile_setting.rb +++ b/db/migrate/20141120110330_create_zonefile_setting.rb @@ -8,6 +8,7 @@ class CreateZonefileSetting < ActiveRecord::Migration t.integer :expire t.integer :minimum_ttl t.string :email + t.string :master_nameserver t.timestamps end @@ -20,7 +21,19 @@ class CreateZonefileSetting < ActiveRecord::Migration retry: 900, expire: 1209600, minimum_ttl: 3600, - email: 'hostmaster.eestiinternet.ee' + email: 'hostmaster.eestiinternet.ee', + master_nameserver: 'ns.tld.ee' + }) + + ZonefileSetting.create({ + origin: 'pri.ee', + ttl: 43200, + refresh: 3600, + retry: 900, + expire: 1209600, + minimum_ttl: 3600, + email: 'hostmaster.eestiinternet.ee', + master_nameserver: 'ns.tld.ee' }) end end diff --git a/db/migrate/20141120140837_add_ee_domain_objects.rb b/db/migrate/20141120140837_add_ee_domain_objects.rb index ab00f7b07..af1a63325 100644 --- a/db/migrate/20141120140837_add_ee_domain_objects.rb +++ b/db/migrate/20141120140837_add_ee_domain_objects.rb @@ -45,14 +45,26 @@ class AddEeDomainObjects < ActiveRecord::Migration admin_contacts: [c], registrar: r ) + + pri = Domain.new( + name: 'pri.ee', + valid_to: Date.new(9999, 1, 1), + period: 1, + period_unit: 'y', + owner_contact: c, + admin_contacts: [c], + registrar: r + ) + + pri.save(validate: false) end # rubocop:enable Metrics/MethodLength def down Domain.find_by(name: 'ee').destroy + Domain.find_by(name: 'pri.ee').destroy EppUser.find_by(username: 'testeis').destroy Contact.find_by(name: 'EIS').destroy Registrar.find_by(name: 'EIS').destroy - end end diff --git a/db/migrate/20141121093125_add_zonefile_procedure.rb b/db/migrate/20141121093125_add_zonefile_procedure.rb index cd92bc635..1eb53d50d 100644 --- a/db/migrate/20141121093125_add_zonefile_procedure.rb +++ b/db/migrate/20141121093125_add_zonefile_procedure.rb @@ -6,17 +6,29 @@ class AddZonefileProcedure < ActiveRecord::Migration RETURNS text AS $$ DECLARE zone_header text := concat('$ORIGIN ', i_origin, '.'); - tmp text := ''; + include_filter varchar := ''; + exclude_filter varchar := ''; ns_records text := ''; a_records text := ''; a4_records text := ''; ds_records text := ''; BEGIN + -- define filters + include_filter = '%' || i_origin; + + -- for %.%.% + IF i_origin ~ '\.' THEN + exclude_filter := ''; + -- for %.% + ELSE + exclude_filter = '%.%.' || i_origin; + END IF; + -- zonefile header SELECT concat( format('%-10s', '$ORIGIN'), i_origin, '.', chr(10), format('%-10s', '$TTL'), zf.ttl, chr(10), chr(10), - format('%-10s', i_origin || '.'), 'IN SOA ', 'ns.tld.ee', '. ', zf.email, '. (', chr(10), + format('%-10s', i_origin || '.'), 'IN SOA ', zf.master_nameserver, '. ', zf.email, '. (', chr(10), format('%-17s', ''), format('%-12s', '2014111210'), '; serial number', chr(10), format('%-17s', ''), format('%-12s', zf.refresh), '; refresh, seconds', chr(10), format('%-17s', ''), format('%-12s', zf.retry), '; retry, seconds', chr(10), @@ -24,14 +36,14 @@ class AddZonefileProcedure < ActiveRecord::Migration format('%-17s', ''), format('%-12s', zf.minimum_ttl), '; minimum TTL, seconds', chr(10), format('%-17s', ''), ')' ) FROM zonefile_settings zf WHERE i_origin = zf.origin INTO zone_header; - + RAISE NOTICE '%', include_filter; -- ns records SELECT array_to_string( array( SELECT concat(d.name, '. IN NS ', ns.hostname, '.') FROM domains d JOIN nameservers ns ON ns.domain_id = d.id - WHERE d.name LIKE '%' || i_origin + WHERE d.name LIKE include_filter ORDER BY CASE d.name WHEN i_origin THEN 1 diff --git a/db/schema.rb b/db/schema.rb index 39a8d94f8..295d7b948 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20141121093125) do +ActiveRecord::Schema.define(version: 20141114130737) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -335,16 +335,4 @@ ActiveRecord::Schema.define(version: 20141121093125) do add_index "versions", ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id", using: :btree - create_table "zonefile_settings", force: true do |t| - t.string "origin" - t.integer "ttl" - t.integer "refresh" - t.integer "retry" - t.integer "expire" - t.integer "minimum_ttl" - t.string "email" - t.datetime "created_at" - t.datetime "updated_at" - end - end diff --git a/db/seeds.rb b/db/seeds.rb index 24d16ffb2..8769d15bc 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -78,13 +78,4 @@ Setting.ns_max_count = 11 Setting.transfer_wait_time = 0 -# rubocop: disable Style/NumericLiterals -Setting.zonefile_ttl = 43200 -Setting.zonefile_refresh = 3600 -Setting.zonefile_retry = 900 -Setting.zonefile_expire = 1209600 -Setting.zonefile_minimum_ttl = 3600 -Setting.zonefile_email = 'hostmaster.eestiinternet.ee' -# rubocop: enable Style/NumericLiterals - # Setting.whois_enabled = true only uncomment this if you wish whois From 98be3c54c3e2a4aaa4b253b090255e8b968b5d48 Mon Sep 17 00:00:00 2001 From: Priit Tamboom Date: Tue, 25 Nov 2014 10:08:44 +0200 Subject: [PATCH 03/13] readme updates from Georg questions --- README.md | 26 ++++++++++++++++++++++++-- db/seeds.rb | 12 ++++++------ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f0ff44346..95e898bb6 100644 --- a/README.md +++ b/README.md @@ -114,13 +114,35 @@ Wait for the greeting message on the STD, then send EPP/TCP frame: ```xml - test - test + registrar1 + test1 sample1trid ``` +All demo data locates at: + + db/seeds.rb + +There are two type of users: admin users and EPP users. + + +### EPP web client + +Please follow EPP web client readme: + + https://github.com/internetee/EPP-web-client + + +### WHOIS server + +Please follow WHOIS server readme: + + https://github.com/internetee/whois + + + Testing --- * Before running tests for the first time: `RAILS_ENV=test rake db:seed` diff --git a/db/seeds.rb b/db/seeds.rb index 8769d15bc..b62cc3614 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -9,7 +9,7 @@ Country.where(name: 'Estonia', iso: 'EE').first_or_create! Country.where(name: 'Latvia', iso: 'LV').first_or_create! -zone = Registrar.where( +registrar1 = Registrar.where( name: 'Registrar First AS', reg_no: '10300220', address: 'Pärnu mnt 2, Tallinna linn, Harju maakond, 11415', @@ -20,10 +20,10 @@ EppUser.where( username: 'registrar1', password: 'test1', active: true, - registrar: zone + registrar: registrar1 ).first_or_create -elkdata = Registrar.where( +registrar2 = Registrar.where( name: 'Registrar Second AS', reg_no: '10529229', address: 'Vabaduse pst 32, 11316 Tallinn', @@ -34,7 +34,7 @@ EppUser.where( username: 'registrar2', password: 'test2', active: true, - registrar: elkdata + registrar: registrar2 ).first_or_create User.where( @@ -52,7 +52,7 @@ User.where( email: 'user2@example.ee', admin: false, identity_code: '37810010085', - registrar_id: zone.id, + registrar_id: registrar1.id, country: Country.where(name: 'Estonia').first ).first_or_create @@ -62,7 +62,7 @@ User.where( email: 'user3@example.ee', admin: false, identity_code: '37810010727', - registrar_id: elkdata.id, + registrar_id: registrar2.id, country: Country.where(name: 'Estonia').first ).first_or_create From 0ccc70fcf46892fb35f37e590f9a302b79d16734 Mon Sep 17 00:00:00 2001 From: Priit Tamboom Date: Tue, 25 Nov 2014 14:51:30 +0200 Subject: [PATCH 04/13] updated readme: added database locale hint --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 95e898bb6..9deef8323 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,12 @@ Usual Rails 4 app installation, rvm and bundler are your friends. rake db:setup mv config/secrets-example.yml config/secrets.yml # generate your own keys +If you desire other database locale, you have to create database manually first and +skip rake db:setup. Example: + + create database registry owner registry encoding 'UTF-8' LC_COLLATE 'et_EE.utf8' LC_CTYPE 'et_EE.utf8' template template0; + rake db:schema:load + rake db:seeds ### Apache with patched mod_epp (Debian 7/Ubuntu 14.04 LTS) From 0ef51a12c42357d2c99b7835d05650358f5ae077 Mon Sep 17 00:00:00 2001 From: Priit Tamboom Date: Tue, 25 Nov 2014 15:28:32 +0200 Subject: [PATCH 05/13] admin login now honors seed file --- app/controllers/sessions_controller.rb | 5 ++++- app/views/layouts/login.haml | 9 ++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 76f4188a2..cdefd70ae 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -3,7 +3,10 @@ class SessionsController < Devise::SessionsController # TODO: Create ID Card login here: # this is just testing config # if Rails.env.development? || Rails.env.test? - @user = User.find_by(username: 'gitlab') if params[:gitlab] + @user = User.first if params[:user1] + @user = User.second if params[:user2] + + return redirect_to :back, alert: 'No user' if @user.blank? session[:current_user_registrar_id] = Registrar.first.id if @user.admin? diff --git a/app/views/layouts/login.haml b/app/views/layouts/login.haml index 7b3a1da76..e516d6817 100644 --- a/app/views/layouts/login.haml +++ b/app/views/layouts/login.haml @@ -5,7 +5,7 @@ %meta{:content => "IE=edge", "http-equiv" => "X-UA-Compatible"}/ %meta{:content => "width=device-width, initial-scale=1", :name => "viewport"}/ %meta{:content => "Full stack top-level domain (TLD) management.", :name => "description"}/ - %meta{:content => "Gitlab LTD", :name => "author"}/ + %meta{:content => "Gitlab Ltd", :name => "author"}/ = csrf_meta_tags = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true = stylesheet_link_tag 'login', media: 'all', 'data-turbolinks-track' => true @@ -22,5 +22,8 @@ %hr / TODO: Refactor this when ID card login is done - if can? :create, :admin_session - = button_to 'ID card (gitlab)', 'sessions', - class: 'btn btn-lg btn-primary btn-block', name: 'gitlab' + = button_to 'ID card (user1)', 'sessions', + class: 'btn btn-lg btn-primary btn-block', name: 'user1' + = button_to 'ID card (user2)', 'sessions', + class: 'btn btn-lg btn-primary btn-block', name: 'user2' + From 0f13de0623720bb8f51cf2558b6f83a16248b5b0 Mon Sep 17 00:00:00 2001 From: Priit Tamboom Date: Tue, 25 Nov 2014 15:37:18 +0200 Subject: [PATCH 06/13] moved menu items domain and jobs under settings --- app/views/admin/domain_versions/show.haml | 2 +- app/views/layouts/application.haml | 28 ++++++++--------------- config/locales/en.yml | 3 ++- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/app/views/admin/domain_versions/show.haml b/app/views/admin/domain_versions/show.haml index 241c508aa..201c79bf9 100644 --- a/app/views/admin/domain_versions/show.haml +++ b/app/views/admin/domain_versions/show.haml @@ -1,7 +1,7 @@ .row .col-sm-6 %h2.text-center-xs - = "#{t('shared.domain_history')} for " + @name.to_s + = "#{t(:domain_history)} for " + @name.to_s .col-sm-6 %h2.text-right.text-center-xs diff --git a/app/views/layouts/application.haml b/app/views/layouts/application.haml index bc449fa96..7a618fd38 100644 --- a/app/views/layouts/application.haml +++ b/app/views/layouts/application.haml @@ -23,34 +23,26 @@ = link_to APP_CONFIG['app_name'], root_path, class: 'navbar-brand' .navbar-collapse.collapse %ul.nav.navbar-nav - %li - = link_to t('shared.domains'), admin_domains_path - %li - = link_to t('shared.contacts'), admin_contacts_path - %li - = link_to t('shared.registrars'), admin_registrars_path + %li= link_to t('shared.domains'), admin_domains_path + %li= link_to t('shared.contacts'), admin_contacts_path + %li= link_to t('shared.registrars'), admin_registrars_path %li.dropdown %a.dropdown-toggle{"data-toggle" => "dropdown", href: "#"} = t('shared.settings') %span.caret %ul.dropdown-menu{role: "menu"} %li.dropdown-header= t('shared.system') - %li - = link_to t('shared.settings'), admin_settings_path - %li - = link_to t('zonefile'), admin_zonefiles_path + %li= link_to t('shared.settings'), admin_settings_path + %li= link_to t(:zonefile), admin_zonefiles_path + %li= link_to t(:domains_history), admin_domain_versions_path + %li= link_to t(:background_jobs), admin_delayed_jobs_path + %li.divider %li.dropdown-header= t('shared.users') - %li - = link_to t('shared.epp_users'), admin_epp_users_path - %li - = link_to t('shared.users'), admin_users_path + %li= link_to t('shared.epp_users'), admin_epp_users_path + %li= link_to t('shared.users'), admin_users_path - %li - = link_to t('shared.domains_history'), admin_domain_versions_path - %li - = link_to t('shared.jobs'), admin_delayed_jobs_path %ul.nav.navbar-nav.navbar-right diff --git a/config/locales/en.yml b/config/locales/en.yml index 4649972c0..ffb1176c4 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -265,7 +265,6 @@ en: registrar: 'Registrar' owner: 'Owner' domain_details: 'Domain details' - domain_history: 'Domain history' registered_at: 'Registered at' password: 'Password' valid_from: 'Valid from' @@ -430,3 +429,5 @@ en: zonefile: 'Zonefile' only_one_parameter_allowed: 'Only one parameter allowed: %{param_1} or %{param_2}' required_parameter_missing_choice: 'Required parameter missing: %{param_1} or %{param_2}' + background_jobs: Background jobs + domain_history: Domain history From aaee412025419ef3d068c41a45816e0547e0cba1 Mon Sep 17 00:00:00 2001 From: Priit Tamboom Date: Tue, 25 Nov 2014 15:41:00 +0200 Subject: [PATCH 07/13] updated menu names: now admin users, epp users --- app/views/layouts/application.haml | 8 +++----- config/locales/en.yml | 2 ++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/views/layouts/application.haml b/app/views/layouts/application.haml index 7a618fd38..f0774ffd3 100644 --- a/app/views/layouts/application.haml +++ b/app/views/layouts/application.haml @@ -39,14 +39,12 @@ %li.divider %li.dropdown-header= t('shared.users') - %li= link_to t('shared.epp_users'), admin_epp_users_path - %li= link_to t('shared.users'), admin_users_path - - - + %li= link_to t(:admin_users), admin_users_path + %li= link_to t(:epp_users), admin_epp_users_path %ul.nav.navbar-nav.navbar-right %li= link_to t('shared.log_out', user: current_user), '/logout' + / /.nav-collapse .container - display = (flash.empty?) ? 'none' : 'block' diff --git a/config/locales/en.yml b/config/locales/en.yml index ffb1176c4..3c1462160 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -431,3 +431,5 @@ en: required_parameter_missing_choice: 'Required parameter missing: %{param_1} or %{param_2}' background_jobs: Background jobs domain_history: Domain history + admin_users: Admin users + epp_users: EPP users From 3b595cb8397fe62e21bbd2fc1f82816b2bbb2909 Mon Sep 17 00:00:00 2001 From: Priit Tamboom Date: Tue, 25 Nov 2014 15:57:40 +0200 Subject: [PATCH 08/13] adde missing translation --- app/views/layouts/client.haml | 2 +- config/locales/en.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/layouts/client.haml b/app/views/layouts/client.haml index 5e220f78d..ff73e2f3f 100644 --- a/app/views/layouts/client.haml +++ b/app/views/layouts/client.haml @@ -57,7 +57,7 @@ %span.caret %ul.dropdown-menu{role: "menu"} %li - = link_to t('shared.domains_history'), client_domain_versions_path + = link_to t(:domains_history'), client_domain_versions_path %li = link_to t('shared.contacts_history'), client_contact_versions_path diff --git a/config/locales/en.yml b/config/locales/en.yml index 3c1462160..460f43d35 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -431,5 +431,6 @@ en: required_parameter_missing_choice: 'Required parameter missing: %{param_1} or %{param_2}' background_jobs: Background jobs domain_history: Domain history + domains_history: Domains history admin_users: Admin users epp_users: EPP users From 623fd25134b0c19f2317c8cc2190f44f084d0878 Mon Sep 17 00:00:00 2001 From: Priit Tamboom Date: Tue, 25 Nov 2014 16:26:19 +0200 Subject: [PATCH 09/13] update spec --- spec/features/sessions_spec.rb | 4 ++-- spec/features/setting_management_spec.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/features/sessions_spec.rb b/spec/features/sessions_spec.rb index d8bc66794..8eb7340c4 100644 --- a/spec/features/sessions_spec.rb +++ b/spec/features/sessions_spec.rb @@ -14,9 +14,9 @@ feature 'Sessions', type: :feature do scenario 'Admin logs in' do visit root_path - expect(page).to have_button('ID card (gitlab)') + expect(page).to have_button('ID card (user1)') - click_on 'ID card (gitlab)' + click_on 'ID card (user1)' expect(page).to have_text('Welcome!') uri = URI.parse(current_url) diff --git a/spec/features/setting_management_spec.rb b/spec/features/setting_management_spec.rb index 20af17a3f..211677c99 100644 --- a/spec/features/setting_management_spec.rb +++ b/spec/features/setting_management_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' feature 'Setting management', type: :feature do let(:zone) { Fabricate(:registrar) } - let(:zone_user) { Fabricate(:user, registrar: zone, username: 'gitlab', admin: true, identity_code: '37810013087') } + let(:zone_user) { Fabricate(:user, registrar: zone, username: 'user1', admin: true, identity_code: '37810013087') } background { create_settings } From e695a6e628d16e2cb43fe974e2647043f4da9146 Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Tue, 25 Nov 2014 17:39:30 +0200 Subject: [PATCH 10/13] Create nameservers cache --- app/controllers/admin/zonefiles_controller.rb | 17 +++++++- app/models/cached_nameserver.rb | 2 + app/models/nameserver.rb | 14 +++++++ app/views/admin/zonefile_settings/index.haml | 2 +- .../20141120140837_add_ee_domain_objects.rb | 20 +++++---- .../20141121093125_add_zonefile_procedure.rb | 41 ++++++++++--------- ...20141125111414_create_nameservers_cache.rb | 16 ++++++++ db/schema.rb | 23 ++++++++++- 8 files changed, 104 insertions(+), 31 deletions(-) create mode 100644 app/models/cached_nameserver.rb create mode 100644 db/migrate/20141125111414_create_nameservers_cache.rb diff --git a/app/controllers/admin/zonefiles_controller.rb b/app/controllers/admin/zonefiles_controller.rb index 811df5627..1eb88687f 100644 --- a/app/controllers/admin/zonefiles_controller.rb +++ b/app/controllers/admin/zonefiles_controller.rb @@ -2,7 +2,20 @@ class Admin::ZonefilesController < ApplicationController # TODO: Refactor this # rubocop:disable Metrics/MethodLength def index - @zonefile = ActiveRecord::Base.connection.execute("select generate_zonefile('ee')")[0]['generate_zonefile'] - send_data @zonefile, filename: 'zonefile-1000.txt' + + end + + def create + if ZonefileSetting.pluck(:origin).include?(params[:origin]) + + @zonefile = ActiveRecord::Base.connection.execute( + "select generate_zonefile('#{params[:origin]}')" + )[0]['generate_zonefile'] + + send_data @zonefile, filename: "#{params[:origin]}.txt" + else + flash[:alert] = 'Origin not supported' + redirect_to :back + end end end diff --git a/app/models/cached_nameserver.rb b/app/models/cached_nameserver.rb new file mode 100644 index 000000000..d465edf83 --- /dev/null +++ b/app/models/cached_nameserver.rb @@ -0,0 +1,2 @@ +class CachedNameserver < ActiveRecord::Base +end diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb index 65373034d..8e1b1d186 100644 --- a/app/models/nameserver.rb +++ b/app/models/nameserver.rb @@ -10,6 +10,10 @@ class Nameserver < ActiveRecord::Base 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 } # rubocop: enable Metrics/LineLength + # caching + after_commit :clear_cache + after_commit :create_cache, on: [:create, :update] + # archiving has_paper_trail class_name: 'NameserverVersion' after_destroy :domain_version @@ -52,6 +56,16 @@ class Nameserver < ActiveRecord::Base domain.create_version if domain end + def create_cache + CachedNameserver.create(snapshot) + rescue ActiveRecord::RecordNotUnique + logger.info('Nameserver already exists in cache; not caching') + end + + def clear_cache + CachedNameserver.find_by(snapshot).try(:delete) + end + def to_s hostname end diff --git a/app/views/admin/zonefile_settings/index.haml b/app/views/admin/zonefile_settings/index.haml index 6e3a7ae17..48411be88 100644 --- a/app/views/admin/zonefile_settings/index.haml +++ b/app/views/admin/zonefile_settings/index.haml @@ -17,4 +17,4 @@ %tr %td= link_to(x, edit_admin_zonefile_setting_path(x)) %td - = link_to(t('generate_zonefile'), admin_zonefiles_path, class: 'btn btn-xs btn-primary') + = link_to(t('generate_zonefile'), admin_zonefiles_path(origin: x.origin), method: 'post', class: 'btn btn-xs btn-primary') diff --git a/db/migrate/20141120140837_add_ee_domain_objects.rb b/db/migrate/20141120140837_add_ee_domain_objects.rb index af1a63325..fb7d296cc 100644 --- a/db/migrate/20141120140837_add_ee_domain_objects.rb +++ b/db/migrate/20141120140837_add_ee_domain_objects.rb @@ -1,14 +1,14 @@ class AddEeDomainObjects < ActiveRecord::Migration # rubocop:disable Metrics/MethodLength def up - r = Registrar.create( + r = Registrar.create!( name: 'EIS', reg_no: '123321', address: 'Tallinn', country: Country.estonia ) - c = Contact.create( + c = Contact.create!( name: 'EIS', phone: '+372.123321', email: 'info@testing.ee', @@ -21,14 +21,14 @@ class AddEeDomainObjects < ActiveRecord::Migration registrar: r ) - EppUser.create( + EppUser.create!( registrar: r, username: 'testeis', password: 'testeis', active: true ) - Domain.create( + Domain.create!( name: 'ee', valid_to: Date.new(9999, 1, 1), period: 1, @@ -46,17 +46,23 @@ class AddEeDomainObjects < ActiveRecord::Migration registrar: r ) - pri = Domain.new( + Domain.create!( name: 'pri.ee', valid_to: Date.new(9999, 1, 1), period: 1, period_unit: 'y', owner_contact: c, + nameservers: [ + Nameserver.create(hostname: 'ns.tld.ee', ipv4: '195.43.87.10'), + Nameserver.create(hostname: 'b.tld.ee', ipv4: '194.146.106.110', ipv6: '2001:67c:1010:28::53'), + Nameserver.create(hostname: 'e.tld.ee', ipv4: '204.61.216.36', ipv6: '2001:678:94:53::53'), + Nameserver.create(hostname: 'ee.aso.ee', ipv4: '213.184.51.122', ipv6: '2a02:88:0:21::2'), + Nameserver.create(hostname: 'ns.ut.ee', ipv4: '193.40.5.99', ipv6: ''), + Nameserver.create(hostname: 'sunic.sunet.se', ipv4: '195.80.103.202') + ], admin_contacts: [c], registrar: r ) - - pri.save(validate: false) end # rubocop:enable Metrics/MethodLength diff --git a/db/migrate/20141121093125_add_zonefile_procedure.rb b/db/migrate/20141121093125_add_zonefile_procedure.rb index 1eb53d50d..59d5f3e2e 100644 --- a/db/migrate/20141121093125_add_zonefile_procedure.rb +++ b/db/migrate/20141121093125_add_zonefile_procedure.rb @@ -17,11 +17,11 @@ class AddZonefileProcedure < ActiveRecord::Migration include_filter = '%' || i_origin; -- for %.%.% - IF i_origin ~ '\.' THEN + IF i_origin ~ '\\.' THEN exclude_filter := ''; -- for %.% ELSE - exclude_filter = '%.%.' || i_origin; + exclude_filter := '%.%.' || i_origin; END IF; -- zonefile header @@ -36,14 +36,14 @@ class AddZonefileProcedure < ActiveRecord::Migration format('%-17s', ''), format('%-12s', zf.minimum_ttl), '; minimum TTL, seconds', chr(10), format('%-17s', ''), ')' ) FROM zonefile_settings zf WHERE i_origin = zf.origin INTO zone_header; - RAISE NOTICE '%', include_filter; + -- ns records SELECT array_to_string( array( SELECT concat(d.name, '. IN NS ', ns.hostname, '.') FROM domains d JOIN nameservers ns ON ns.domain_id = d.id - WHERE d.name LIKE include_filter + WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter ORDER BY CASE d.name WHEN i_origin THEN 1 @@ -52,17 +52,25 @@ class AddZonefileProcedure < ActiveRecord::Migration chr(10) ) INTO ns_records; + -- use caching + + /*SELECT concat(cns.hostname, '. IN A ', cns.ipv4, '.') FROM cached_nameservers cns WHERE EXISTS ( + SELECT 1 + FROM nameservers ns + JOIN domains d ON d.id = ns.domain_id + WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter + AND ns.hostname = cns.hostname AND ns.ipv4 = cns.ipv4 AND ns.ipv6 = cns.ipv6 + AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> '' + );*/ + -- a records SELECT array_to_string( array( SELECT concat(ns.hostname, '. IN A ', ns.ipv4, '.') FROM domains d JOIN nameservers ns ON ns.domain_id = d.id - WHERE d.name LIKE '%' || i_origin AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> '' - ORDER BY - CASE d.name - WHEN i_origin THEN 1 - END + WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter + AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> '' ), chr(10) ) INTO a_records; @@ -73,11 +81,8 @@ class AddZonefileProcedure < ActiveRecord::Migration SELECT concat(ns.hostname, '. IN AAAA ', ns.ipv6, '.') FROM domains d JOIN nameservers ns ON ns.domain_id = d.id - WHERE d.name LIKE '%' || i_origin AND ns.ipv6 IS NOT NULL AND ns.ipv6 <> '' - ORDER BY - CASE d.name - WHEN i_origin THEN 1 - END + WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter + AND ns.ipv6 IS NOT NULL AND ns.ipv6 <> '' ), chr(10) ) INTO a4_records; @@ -86,16 +91,12 @@ class AddZonefileProcedure < ActiveRecord::Migration SELECT array_to_string( array( SELECT concat( - d.name, '. 86400 IN ', dk.ds_key_tag, ' ', + d.name, '. 86400 IN DS ', dk.ds_key_tag, ' ', dk.ds_alg, ' ', dk.ds_digest_type, ' ', dk.ds_digest ) FROM domains d JOIN dnskeys dk ON dk.domain_id = d.id - WHERE d.name LIKE '%' || i_origin - ORDER BY - CASE d.name - WHEN i_origin THEN 1 - END + WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter ), chr(10) ) INTO ds_records; diff --git a/db/migrate/20141125111414_create_nameservers_cache.rb b/db/migrate/20141125111414_create_nameservers_cache.rb new file mode 100644 index 000000000..db56cd767 --- /dev/null +++ b/db/migrate/20141125111414_create_nameservers_cache.rb @@ -0,0 +1,16 @@ +class CreateNameserversCache < ActiveRecord::Migration + def change + create_table :cached_nameservers, id: false do |t| + t.string :hostname + t.string :ipv4 + t.string :ipv6 + end + add_index :cached_nameservers, [:hostname, :ipv4, :ipv6], unique: true + + execute <<-SQL + INSERT INTO cached_nameservers ( + SELECT ns.hostname, ns.ipv4, ns.ipv6 FROM nameservers ns GROUP BY ns.hostname, ns.ipv4, ns.ipv6 + ); + SQL + end +end diff --git a/db/schema.rb b/db/schema.rb index 295d7b948..ec3684f36 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20141114130737) do +ActiveRecord::Schema.define(version: 20141125111414) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -39,6 +39,14 @@ ActiveRecord::Schema.define(version: 20141114130737) do t.string "street3" end + create_table "cached_nameservers", id: false, force: true do |t| + t.string "hostname" + t.string "ipv4" + t.string "ipv6" + end + + add_index "cached_nameservers", ["hostname", "ipv4", "ipv6"], name: "index_cached_nameservers_on_hostname_and_ipv4_and_ipv6", unique: true, using: :btree + create_table "contact_disclosures", force: true do |t| t.integer "contact_id" t.boolean "int_name", default: false @@ -335,4 +343,17 @@ ActiveRecord::Schema.define(version: 20141114130737) do add_index "versions", ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id", using: :btree + create_table "zonefile_settings", force: true do |t| + t.string "origin" + t.integer "ttl" + t.integer "refresh" + t.integer "retry" + t.integer "expire" + t.integer "minimum_ttl" + t.string "email" + t.string "master_nameserver" + t.datetime "created_at" + t.datetime "updated_at" + end + end From b58417cbee6a5ed3356fdb351072eff5e1cb9c2c Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Wed, 26 Nov 2014 15:05:10 +0200 Subject: [PATCH 11/13] Use cached nameservers in zonefile procedure --- .../20141121093125_add_zonefile_procedure.rb | 37 ++++++++----------- ...20141125111414_create_nameservers_cache.rb | 6 ++- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/db/migrate/20141121093125_add_zonefile_procedure.rb b/db/migrate/20141121093125_add_zonefile_procedure.rb index 59d5f3e2e..d4c710f98 100644 --- a/db/migrate/20141121093125_add_zonefile_procedure.rb +++ b/db/migrate/20141121093125_add_zonefile_procedure.rb @@ -52,25 +52,17 @@ class AddZonefileProcedure < ActiveRecord::Migration chr(10) ) INTO ns_records; - -- use caching - - /*SELECT concat(cns.hostname, '. IN A ', cns.ipv4, '.') FROM cached_nameservers cns WHERE EXISTS ( - SELECT 1 - FROM nameservers ns - JOIN domains d ON d.id = ns.domain_id - WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter - AND ns.hostname = cns.hostname AND ns.ipv4 = cns.ipv4 AND ns.ipv6 = cns.ipv6 - AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> '' - );*/ - -- a records SELECT array_to_string( array( - SELECT concat(ns.hostname, '. IN A ', ns.ipv4, '.') - FROM domains d - JOIN nameservers ns ON ns.domain_id = d.id - WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter - AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> '' + SELECT concat(cns.hostname, '. IN A ', cns.ipv4, '.') FROM cached_nameservers cns WHERE EXISTS ( + SELECT 1 + FROM nameservers ns + JOIN domains d ON d.id = ns.domain_id + WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter + AND ns.hostname = cns.hostname AND ns.ipv4 = cns.ipv4 AND ns.ipv6 = cns.ipv6 + AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> '' + ) ), chr(10) ) INTO a_records; @@ -78,11 +70,14 @@ class AddZonefileProcedure < ActiveRecord::Migration -- aaaa records SELECT array_to_string( array( - SELECT concat(ns.hostname, '. IN AAAA ', ns.ipv6, '.') - FROM domains d - JOIN nameservers ns ON ns.domain_id = d.id - WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter - AND ns.ipv6 IS NOT NULL AND ns.ipv6 <> '' + SELECT concat(cns.hostname, '. IN AAAA ', cns.ipv6, '.') FROM cached_nameservers cns WHERE EXISTS ( + SELECT 1 + FROM nameservers ns + JOIN domains d ON d.id = ns.domain_id + WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter + AND ns.hostname = cns.hostname AND ns.ipv6 = cns.ipv6 AND ns.ipv6 = cns.ipv6 + AND ns.ipv6 IS NOT NULL AND ns.ipv6 <> '' + ) ), chr(10) ) INTO a4_records; diff --git a/db/migrate/20141125111414_create_nameservers_cache.rb b/db/migrate/20141125111414_create_nameservers_cache.rb index db56cd767..f305e7e1c 100644 --- a/db/migrate/20141125111414_create_nameservers_cache.rb +++ b/db/migrate/20141125111414_create_nameservers_cache.rb @@ -1,5 +1,5 @@ class CreateNameserversCache < ActiveRecord::Migration - def change + def up create_table :cached_nameservers, id: false do |t| t.string :hostname t.string :ipv4 @@ -13,4 +13,8 @@ class CreateNameserversCache < ActiveRecord::Migration ); SQL end + + def down + drop_table :cached_nameservers + end end From a88109021ec220cee8ba838fd1f33329cb491182 Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Wed, 26 Nov 2014 15:18:41 +0200 Subject: [PATCH 12/13] Rubocop fix --- app/controllers/admin/zonefiles_controller.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/admin/zonefiles_controller.rb b/app/controllers/admin/zonefiles_controller.rb index 1eb88687f..d99494ee5 100644 --- a/app/controllers/admin/zonefiles_controller.rb +++ b/app/controllers/admin/zonefiles_controller.rb @@ -2,7 +2,6 @@ class Admin::ZonefilesController < ApplicationController # TODO: Refactor this # rubocop:disable Metrics/MethodLength def index - end def create From b022ddee3a8318b30e61b5963f12665dc57cf587 Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Fri, 28 Nov 2014 15:14:24 +0200 Subject: [PATCH 13/13] Add dynamic serial number to zonefile procedure --- ...140434_add_serial_to_zonefile_procedure.rb | 120 ++++++++++++++++++ db/schema.rb | 2 +- 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20141126140434_add_serial_to_zonefile_procedure.rb diff --git a/db/migrate/20141126140434_add_serial_to_zonefile_procedure.rb b/db/migrate/20141126140434_add_serial_to_zonefile_procedure.rb new file mode 100644 index 000000000..d02270e39 --- /dev/null +++ b/db/migrate/20141126140434_add_serial_to_zonefile_procedure.rb @@ -0,0 +1,120 @@ +class AddSerialToZonefileProcedure < ActiveRecord::Migration + # rubocop:disable Metrics/MethodLength + def up + execute <<-SQL + CREATE OR REPLACE FUNCTION generate_zonefile(i_origin varchar) + RETURNS text AS $$ + DECLARE + zone_header text := concat('$ORIGIN ', i_origin, '.'); + serial_num varchar; + include_filter varchar := ''; + exclude_filter varchar := ''; + ns_records text := ''; + a_records text := ''; + a4_records text := ''; + ds_records text := ''; + BEGIN + -- define filters + include_filter = '%' || i_origin; + + -- for %.%.% + IF i_origin ~ '\\.' THEN + exclude_filter := ''; + -- for %.% + ELSE + exclude_filter := '%.%.' || i_origin; + END IF; + + SELECT ROUND(extract(epoch from now() at time zone 'utc')) INTO serial_num; + + -- zonefile header + SELECT concat( + format('%-10s', '$ORIGIN'), i_origin, '.', chr(10), + format('%-10s', '$TTL'), zf.ttl, chr(10), chr(10), + format('%-10s', i_origin || '.'), 'IN SOA ', zf.master_nameserver, '. ', zf.email, '. (', chr(10), + format('%-17s', ''), format('%-12s', serial_num), '; serial number', chr(10), + format('%-17s', ''), format('%-12s', zf.refresh), '; refresh, seconds', chr(10), + format('%-17s', ''), format('%-12s', zf.retry), '; retry, seconds', chr(10), + format('%-17s', ''), format('%-12s', zf.expire), '; expire, seconds', chr(10), + format('%-17s', ''), format('%-12s', zf.minimum_ttl), '; minimum TTL, seconds', chr(10), + format('%-17s', ''), ')' + ) FROM zonefile_settings zf WHERE i_origin = zf.origin INTO zone_header; + + -- ns records + SELECT array_to_string( + array( + SELECT concat(d.name, '. IN NS ', ns.hostname, '.') + FROM domains d + JOIN nameservers ns ON ns.domain_id = d.id + WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter + ORDER BY + CASE d.name + WHEN i_origin THEN 1 + END + ), + chr(10) + ) INTO ns_records; + + -- a records + SELECT array_to_string( + array( + SELECT concat(cns.hostname, '. IN A ', cns.ipv4, '.') FROM cached_nameservers cns WHERE EXISTS ( + SELECT 1 + FROM nameservers ns + JOIN domains d ON d.id = ns.domain_id + WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter + AND ns.hostname = cns.hostname AND ns.ipv4 = cns.ipv4 AND ns.ipv6 = cns.ipv6 + AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> '' + ) + ), + chr(10) + ) INTO a_records; + + -- aaaa records + SELECT array_to_string( + array( + SELECT concat(cns.hostname, '. IN AAAA ', cns.ipv6, '.') FROM cached_nameservers cns WHERE EXISTS ( + SELECT 1 + FROM nameservers ns + JOIN domains d ON d.id = ns.domain_id + WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter + AND ns.hostname = cns.hostname AND ns.ipv6 = cns.ipv6 AND ns.ipv6 = cns.ipv6 + AND ns.ipv6 IS NOT NULL AND ns.ipv6 <> '' + ) + ), + chr(10) + ) INTO a4_records; + + -- ds records + SELECT array_to_string( + array( + SELECT concat( + d.name, '. 86400 IN DS ', dk.ds_key_tag, ' ', + dk.ds_alg, ' ', dk.ds_digest_type, ' ', dk.ds_digest + ) + FROM domains d + JOIN dnskeys dk ON dk.domain_id = d.id + WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter + ), + chr(10) + ) INTO ds_records; + + RETURN concat( + zone_header, chr(10), chr(10), + '; Zone NS Records', chr(10), ns_records, chr(10), chr(10), + '; Zone A Records', chr(10), a_records, chr(10), chr(10), + '; Zone AAAA Records', chr(10), a4_records, chr(10), chr(10), + '; Zone DS Records', chr(10), ds_records + ); + END; + $$ + LANGUAGE plpgsql; + SQL + end + + def down + execute <<-SQL + DROP FUNCTION generate_zonefile(i_origin varchar); + SQL + end +end diff --git a/db/schema.rb b/db/schema.rb index ec3684f36..c0d21071d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20141125111414) do +ActiveRecord::Schema.define(version: 20141126140434) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql"