diff --git a/.rubocop-guard.yml b/.rubocop-guard.yml
new file mode 100644
index 000000000..0ee03be6b
--- /dev/null
+++ b/.rubocop-guard.yml
@@ -0,0 +1,10 @@
+inherit_from: .rubocop.yml
+
+#
+# Turn off during guard runs
+#
+
+# turn off comment intention check during development
+# because NerdCommenter honors commented code intentions
+Style/CommentIndentation:
+ Enabled: false
diff --git a/.rubocop.yml b/.rubocop.yml
index ce05b727c..feaf4db68 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -14,6 +14,12 @@ AllCops:
Metrics/LineLength:
Max: 120
+Metrics/MethodLength:
+ Max: 25 # default 10
+
+Metrics/ClassLength:
+ Max: 300
+
Documentation:
Enabled: false
@@ -29,11 +35,30 @@ Style/BracesAroundHashParameters:
Style/IndentHash:
Enabled: false
+# a bit too annoying requirement, no big drawback yet dedected
+Style/TrailingWhitespace:
+ Enabled: false
+
+# allow == operator used in void context in specs
+Void:
+ Exclude:
+ - 'spec/**/*'
+
+# allow should == nil in spec
+Style/NilComparison:
+ Exclude:
+ - 'spec/**/*'
+
# No need to force reduce to use |a, e| as parameters.
# Configuration parameters: Methods.
Style/SingleLineBlockParams:
Enabled: false
-# No need for nested module/class definition as far as I know
+# allow prefix for models and controllers,
+# otherwise we have to intent all body 4 spaces
Style/ClassAndModuleChildren:
Enabled: false
+
+# Allow to use Estonian terms/data in comments
+Style/AsciiComments:
+ Enabled: false
diff --git a/Gemfile b/Gemfile
index 68c15b8a3..5014e517f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -64,30 +64,8 @@ gem 'paper_trail', '~> 3.0.5'
# for select
gem 'selectize-rails', '~> 0.11.0'
-group :assets do
- # See https://github.com/sstephenson/execjs#readme for more supported runtimes
- gem 'therubyracer', platforms: :ruby
-end
-
-group :development do
- # faster dev load time
- gem 'unicorn'
-
- # Spring speeds up development by keeping your application running in the background.
- # Read more: https://github.com/rails/spring
- gem 'spring'
-
- # bundle exec rake doc:rails generates the API under doc/api.
- gem 'sdoc', '~> 0.4.0'
-
- # run tests automatically
- gem 'guard', '~> 2.6.1'
-
- # rspec support for guard
- gem 'guard-rspec', '~> 4.3.1'
- # rubocop support for guard
- gem 'guard-rubocop', '~> 1.1.0'
-end
+# See https://github.com/sstephenson/execjs#readme for more supported runtimes
+gem 'therubyracer', platforms: :ruby
group :development, :test do
gem 'capybara', '~> 2.4.1'
@@ -123,5 +101,39 @@ group :development, :test do
gem 'uuidtools', '~> 2.1.4'
# For code review
- gem 'simplecov', '~> 0.9.1', :require => false
+ gem 'simplecov', '~> 0.9.1', require: false
+ gem 'rubycritic', '~> 1.1.1'
+
+ # for finding database optimizations
+ gem 'bullet', '~> 4.14.0'
+
+ # for finding future vulnerable gems
+ gem 'bundler-audit'
+
+ # for security audit'
+ gem 'brakeman', '~> 2.6.2', require: false
+
+ # Spring speeds up development by keeping your application running in the background.
+ # Read more: https://github.com/rails/spring
+ gem 'spring'
+
+ # bundle exec rake doc:rails generates the API under doc/api.
+ gem 'sdoc', '~> 0.4.0'
+
+ # run tests automatically
+ gem 'guard', '~> 2.6.1'
+
+ # rspec support for guard
+ gem 'guard-rspec', '~> 4.3.1'
+ gem 'rubocop', '~> 0.26.1'
+ gem 'guard-rubocop', '~> 1.1.0'
+
+ # for quick debugging
+ gem 'web-console', '~> 2.0.0.beta4'
+
+ # for finding dead routes and unused actions
+ gem 'traceroute', '~> 0.4.0'
+
+ # faster dev load time
+ gem 'unicorn'
end
diff --git a/Gemfile.lock b/Gemfile.lock
index a6a6c8c77..6a8fe5b70 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -31,12 +31,35 @@ GEM
ast (2.0.0)
astrolabe (1.3.0)
parser (>= 2.2.0.pre.3, < 3.0)
+ axiom-types (0.1.1)
+ descendants_tracker (~> 0.0.4)
+ ice_nine (~> 0.11.0)
+ thread_safe (~> 0.3, >= 0.3.1)
bcrypt (3.1.7)
+ binding_of_caller (0.7.3.pre1)
+ debug_inspector (>= 0.0.1)
bootstrap-sass (3.2.0.2)
sass (~> 3.2)
+ brakeman (2.6.2)
+ erubis (~> 2.6)
+ fastercsv (~> 1.5)
+ haml (>= 3.0, < 5.0)
+ highline (~> 1.6.20)
+ multi_json (~> 1.2)
+ ruby2ruby (~> 2.1.1)
+ ruby_parser (~> 3.5.0)
+ sass (~> 3.0)
+ slim (>= 1.3.6, < 3.0)
+ terminal-table (~> 1.4)
builder (3.2.2)
+ bullet (4.14.0)
+ activesupport (>= 3.0.0)
+ uniform_notifier (>= 1.6.0)
+ bundler-audit (0.3.1)
+ bundler (~> 1.2)
+ thor (~> 0.18)
cancan (1.6.10)
- capybara (2.4.1)
+ capybara (2.4.3)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
@@ -46,14 +69,19 @@ GEM
timers (~> 4.0.0)
cliver (0.3.2)
coderay (1.1.0)
+ coercible (1.0.0)
+ descendants_tracker (~> 0.0.1)
coffee-rails (4.0.1)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.0)
coffee-script (2.3.0)
coffee-script-source
execjs
- coffee-script-source (1.7.0)
+ coffee-script-source (1.8.0)
database_cleaner (1.3.0)
+ debug_inspector (0.0.2)
+ descendants_tracker (0.0.4)
+ thread_safe (~> 0.3, >= 0.3.1)
devise (3.3.0)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
@@ -65,12 +93,20 @@ GEM
epp (1.4.0)
hpricot
libxml-ruby
+ equalizer (0.0.9)
erubis (2.7.0)
execjs (2.2.1)
fabrication (2.11.3)
faker (1.3.0)
i18n (~> 0.5)
- ffi (1.9.3)
+ fastercsv (1.5.5)
+ ffi (1.9.6)
+ flay (2.4.0)
+ ruby_parser (~> 3.0)
+ sexp_processor (~> 4.0)
+ flog (4.2.1)
+ ruby_parser (~> 3.1, > 3.1.0)
+ sexp_processor (~> 4.4)
formatador (0.2.5)
guard (2.6.1)
formatador (>= 0.2.4)
@@ -91,12 +127,14 @@ GEM
activesupport (>= 4.0.1)
haml (>= 3.1, < 5.0)
railties (>= 4.0.1)
+ highline (1.6.21)
hike (1.2.3)
hitimes (1.2.2)
hpricot (0.8.6)
i18n (0.6.11)
+ ice_nine (0.11.0)
isikukood (0.1.2)
- jbuilder (2.1.3)
+ jbuilder (2.2.2)
activesupport (>= 3.0.0, < 5)
multi_json (~> 1.2)
jquery-rails (3.1.2)
@@ -107,9 +145,9 @@ GEM
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kgio (2.9.2)
- libv8 (3.16.14.5)
+ libv8 (3.16.14.7)
libxml-ruby (2.7.0)
- listen (2.7.9)
+ listen (2.7.11)
celluloid (>= 0.15.2)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
@@ -120,16 +158,16 @@ GEM
method_source (0.8.2)
mime-types (1.25.1)
mini_portile (0.6.0)
- minitest (5.4.1)
+ minitest (5.4.2)
multi_json (1.10.1)
nokogiri (1.6.2.1)
mini_portile (= 0.6.0)
nprogress-rails (0.1.3.1)
orm_adapter (0.5.0)
- paper_trail (3.0.5)
+ paper_trail (3.0.6)
activerecord (>= 3.0, < 5.0)
activesupport (>= 3.0, < 5.0)
- parser (2.2.0.pre.4)
+ parser (2.2.0.pre.5)
ast (>= 1.1, < 3.0)
slop (~> 3.4, >= 3.4.5)
pg (0.17.1)
@@ -181,6 +219,11 @@ GEM
ffi (>= 0.5.0)
rdoc (4.1.2)
json (~> 1.4)
+ reek (1.3.8)
+ rainbow (>= 1.99, < 3.0)
+ ruby2ruby (>= 2.0.8, < 3.0)
+ ruby_parser (~> 3.3)
+ sexp_processor
ref (1.0.5)
rspec (3.0.0)
rspec-core (~> 3.0.0)
@@ -202,13 +245,25 @@ GEM
rspec-mocks (~> 3.0.0)
rspec-support (~> 3.0.0)
rspec-support (3.0.4)
- rubocop (0.26.0)
+ rubocop (0.26.1)
astrolabe (~> 1.3)
parser (>= 2.2.0.pre.4, < 3.0)
powerpack (~> 0.0.6)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.4)
- ruby-progressbar (1.5.1)
+ ruby-progressbar (1.6.0)
+ ruby2ruby (2.1.3)
+ ruby_parser (~> 3.1)
+ sexp_processor (~> 4.0)
+ ruby_parser (3.5.0)
+ sexp_processor (~> 4.1)
+ rubycritic (1.1.1)
+ flay (= 2.4.0)
+ flog (= 4.2.1)
+ parser (~> 2.1)
+ reek (= 1.3.8)
+ ruby2ruby (>= 2.1.1, < 3.0)
+ virtus (~> 1.0)
sass (3.2.19)
sass-rails (4.0.3)
railties (>= 4.0.0, < 5.0)
@@ -219,6 +274,7 @@ GEM
json (~> 1.7, >= 1.7.7)
rdoc (~> 4.0)
selectize-rails (0.11.0)
+ sexp_processor (4.4.4)
shoulda-matchers (2.6.2)
activesupport (>= 3.0.0)
simplecov (0.9.1)
@@ -227,9 +283,12 @@ GEM
simplecov-html (~> 0.8.0)
simplecov-html (0.8.0)
simpleidn (0.0.5)
+ slim (2.0.3)
+ temple (~> 0.6.6)
+ tilt (>= 1.3.3, < 2.1)
slop (3.6.0)
spring (1.1.3)
- sprockets (2.11.0)
+ sprockets (2.8.0)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
@@ -240,6 +299,8 @@ GEM
sprockets (~> 2.8)
sys-uname (0.9.0)
ffi (>= 1.0.0)
+ temple (0.6.8)
+ terminal-table (1.4.5)
therubyracer (0.12.1)
libv8 (~> 3.16.14.0)
ref
@@ -248,10 +309,12 @@ GEM
tilt (1.4.1)
timers (4.0.1)
hitimes
+ traceroute (0.4.0)
+ rails (>= 3.0.0)
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
- turbolinks (2.3.0)
+ turbolinks (2.4.0)
coffee-rails
tzinfo (1.2.2)
thread_safe (~> 0.1)
@@ -262,10 +325,21 @@ GEM
kgio (~> 2.6)
rack
raindrops (~> 0.7)
+ uniform_notifier (1.6.2)
uuidtools (2.1.5)
+ virtus (1.0.3)
+ axiom-types (~> 0.1)
+ coercible (~> 1.0)
+ descendants_tracker (~> 0.0, >= 0.0.3)
+ equalizer (~> 0.0, >= 0.0.9)
warden (1.2.3)
rack (>= 1.0)
- websocket-driver (0.3.4)
+ web-console (2.0.0.beta4)
+ activemodel (~> 4.0)
+ binding_of_caller (= 0.7.3.pre1)
+ railties (~> 4.0)
+ sprockets-rails (>= 2.0, < 4.0)
+ websocket-driver (0.3.5)
xpath (2.0.0)
nokogiri (~> 1.3)
@@ -274,6 +348,9 @@ PLATFORMS
DEPENDENCIES
bootstrap-sass (~> 3.2.0.1)
+ brakeman (~> 2.6.2)
+ bullet (~> 4.14.0)
+ bundler-audit
cancan (~> 1.6.10)
capybara (~> 2.4.1)
coffee-rails (~> 4.0.0)
@@ -301,6 +378,8 @@ DEPENDENCIES
rails (= 4.1.4)
ransack (~> 1.3.0)
rspec-rails (~> 3.0.2)
+ rubocop (~> 0.26.1)
+ rubycritic (~> 1.1.1)
sass-rails (~> 4.0.3)
sdoc (~> 0.4.0)
selectize-rails (~> 0.11.0)
@@ -309,7 +388,9 @@ DEPENDENCIES
simpleidn (~> 0.0.5)
spring
therubyracer
+ traceroute (~> 0.4.0)
turbolinks
uglifier (>= 1.3.0)
unicorn
uuidtools (~> 2.1.4)
+ web-console (~> 2.0.0.beta4)
diff --git a/Guardfile b/Guardfile
index 972130966..a915ec3ee 100644
--- a/Guardfile
+++ b/Guardfile
@@ -1,5 +1,5 @@
-group :red_green_refactor, halt_on_fail:true do
- guard :rspec, cmd: 'bundle exec rspec' do
+group :red_green_refactor, halt_on_fail: true do
+ guard :rspec, cmd: 'bundle exec rspec', notification: false do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" }
@@ -26,9 +26,10 @@ group :red_green_refactor, halt_on_fail:true do
# Martin does not want rubocop
unless Socket.gethostname == 'martin'
- guard :rubocop do
+ guard :rubocop, cli: '--display-cop-names -c .rubocop-guard.yml', notification: false do
watch(%r{.+\.rb$})
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
+ watch(%r{(?:.+/)?\.rubocop-guard\.yml$}) { |m| File.dirname(m[0]) }
end
end
end
diff --git a/app/controllers/admin/contact_versions_controller.rb b/app/controllers/admin/contact_versions_controller.rb
index 4748cff3a..1636a24ab 100644
--- a/app/controllers/admin/contact_versions_controller.rb
+++ b/app/controllers/admin/contact_versions_controller.rb
@@ -11,6 +11,7 @@ class Admin::ContactVersionsController < AdminController
end
private
+
def set_contact
@contact = Contact.find(params[:id])
end
diff --git a/app/controllers/admin/domain_versions_controller.rb b/app/controllers/admin/domain_versions_controller.rb
index 784b2553a..297f04ecb 100644
--- a/app/controllers/admin/domain_versions_controller.rb
+++ b/app/controllers/admin/domain_versions_controller.rb
@@ -11,6 +11,7 @@ class Admin::DomainVersionsController < AdminController
end
private
+
def set_domain
@domain = Domain.find(params[:id])
end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index d4e208a82..a65460c17 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -53,6 +53,7 @@ class Admin::UsersController < AdminController
end
def user_params
- params.require(:user).permit(:username, :password, :identity_code, :email, :registrar_id, :admin, :registrar_typeahead, :country_id)
+ params.require(:user).permit(:username, :password, :identity_code, :email, :registrar_id,
+ :admin, :registrar_typeahead, :country_id)
end
end
diff --git a/app/controllers/client/contacts_controller.rb b/app/controllers/client/contacts_controller.rb
index 40a9b0b63..fe34502ce 100644
--- a/app/controllers/client/contacts_controller.rb
+++ b/app/controllers/client/contacts_controller.rb
@@ -12,10 +12,12 @@ class Client::ContactsController < ClientController
end
def show
+ # rubocop: disable Style/GuardClause
if @contact.registrar != current_registrar
flash[:alert] = I18n.t('shared.authentication_error')
redirect_to client_contacts_path
end
+ # rubocop: enable Style/GuardClause
end
def create
@@ -27,7 +29,7 @@ class Client::ContactsController < ClientController
redirect_to [:client, @contact]
else
flash[:alert] = I18n.t('shared.failed_to_create_contact')
- render "new"
+ render 'new'
end
end
@@ -63,7 +65,7 @@ class Client::ContactsController < ClientController
end
def contact_params
- params.require(:contact).permit( :email, :phone, :fax, :ident_type, :ident, :auth_info, :name, :org_name,
+ params.require(:contact).permit(:email, :phone, :fax, :ident_type, :ident, :auth_info, :name, :org_name,
address_attributes: [:city, :street, :zip, :street2, :street3, :country_id])
end
end
diff --git a/app/controllers/client/domain_transfers_controller.rb b/app/controllers/client/domain_transfers_controller.rb
index ec1711264..9a8de11ef 100644
--- a/app/controllers/client/domain_transfers_controller.rb
+++ b/app/controllers/client/domain_transfers_controller.rb
@@ -12,6 +12,8 @@ class Client::DomainTransfersController < ClientController
@domain_transfer = DomainTransfer.new
end
+ # rubocop: disable Metrics/PerceivedComplexity
+ # rubocop: disable Metrics/CyclomaticComplexity
def create
@domain_transfer = @domain.pending_transfer
@@ -36,6 +38,8 @@ class Client::DomainTransfersController < ClientController
redirect_to [:client, @domain_transfer]
end
end
+ # rubocop: enable Metrics/PerceivedComplexity
+ # rubocop: enable Metrics/CyclomaticComplexity
def approve
if can? :approve_as_client, @domain_transfer
@@ -63,6 +67,8 @@ class Client::DomainTransfersController < ClientController
}
end
+ # rubocop: disable Metrics/PerceivedComplexity
+ # rubocop: disable Metrics/CyclomaticComplexity
def set_domain
@domain_transfer = DomainTransfer.new
@domain = Domain.find_by(name: params[:domain_name])
@@ -81,4 +87,6 @@ class Client::DomainTransfersController < ClientController
render 'new'
end
end
+ # rubocop: enbale Metrics/PerceivedComplexity
+ # rubocop: enable Metrics/CyclomaticComplexity
end
diff --git a/app/controllers/concerns/epp/common.rb b/app/controllers/concerns/epp/common.rb
index c18ed2ea0..d43b82190 100644
--- a/app/controllers/concerns/epp/common.rb
+++ b/app/controllers/concerns/epp/common.rb
@@ -14,7 +14,9 @@ module Epp::Common
end
def proxy
- @svTRID = "ccReg-#{'%010d' % rand(10**10)}"
+ # rubocop: disable Style/VariableName
+ @svTRID = "ccReg-#{format('%010d', rand(10**10))}"
+ # rubocop: enable Style/VariableName
send(params[:command])
end
@@ -46,7 +48,10 @@ module Epp::Common
end
# for debugging
- @errors << { code: '1', msg: 'handle_errors was executed when there were actually no errors' } if @errors.blank?
+ @errors << {
+ code: '1',
+ msg: 'handle_errors was executed when there were actually no errors'
+ } if @errors.blank?
@errors.uniq!
@@ -60,7 +65,10 @@ module Epp::Common
def xml_attrs_present?(ph, attributes)
attributes.each do |x|
- epp_errors << { code: '2003', msg: I18n.t('errors.messages.required_parameter_missing', key: x.last) } unless has_attribute(ph, x)
+ epp_errors << {
+ code: '2003',
+ msg: I18n.t('errors.messages.required_parameter_missing', key: x.last)
+ } unless has_attribute(ph, x)
end
epp_errors.empty?
end
@@ -68,24 +76,27 @@ module Epp::Common
def xml_attrs_array_present?(array_ph, attributes)
[array_ph].flatten.each do |ph|
attributes.each do |x|
- unless has_attribute(ph, x)
- epp_errors << { code: '2003', msg: I18n.t('errors.messages.required_parameter_missing', key: x.last) }
- end
+ next if has_attribute(ph, x)
+ epp_errors << {
+ code: '2003',
+ msg: I18n.t('errors.messages.required_parameter_missing', key: x.last)
+ }
end
end
epp_errors.empty?
end
+ # rubocop: disable Style/PredicateName
def has_attribute(ph, path)
path.reduce(ph) do |location, key|
location.respond_to?(:keys) ? location[key] : nil
end
end
+ # rubocop: enable Style/PredicateName
def validate_request
validation_method = "validate_#{OBJECT_TYPES[params_hash['epp']['xmlns:ns2']]}_#{params[:command]}_request"
- if respond_to?(validation_method, true)
- handle_errors and return unless send(validation_method)
- end
+ return unless respond_to?(validation_method, true)
+ handle_errors and return unless send(validation_method)
end
end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 8af49734a..c878393e1 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -1,6 +1,6 @@
class SessionsController < Devise::SessionsController
def create
- #TODO: Create ID Card login here:
+ # 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]
@@ -10,8 +10,7 @@ class SessionsController < Devise::SessionsController
session[:current_user_registrar_id] = Registrar.first.id if @user.admin?
flash[:notice] = I18n.t('shared.welcome')
- sign_in_and_redirect @user, :event => :authentication
- return
+ sign_in_and_redirect @user, event: :authentication
# end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 7e225ced6..77cfbedb3 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1,5 +1,5 @@
module ApplicationHelper
def coffee_script_tag(&block)
- content_tag(:script, CoffeeScript.compile(capture(&block)).html_safe, :type => 'text/javascript')
+ content_tag(:script, CoffeeScript.compile(capture(&block)).html_safe, type: 'text/javascript')
end
end
diff --git a/app/helpers/epp/contacts_helper.rb b/app/helpers/epp/contacts_helper.rb
index 083e85253..6a65b774e 100644
--- a/app/helpers/epp/contacts_helper.rb
+++ b/app/helpers/epp/contacts_helper.rb
@@ -20,6 +20,7 @@ module Epp::ContactsHelper
end
end
+ # rubocop:disable Metrics/CyclomaticComplexity
def delete_contact
@contact = find_contact
handle_errors(@contact) and return unless owner?
@@ -28,6 +29,7 @@ module Epp::ContactsHelper
render '/epp/contacts/delete'
end
+ # rubocop:enable Metrics/CyclomaticComplexity
def check_contact
ph = params_hash['epp']['command']['check']['check']
@@ -54,11 +56,11 @@ module Epp::ContactsHelper
## CREATE
def validate_contact_create_request
@ph = params_hash['epp']['command']['create']['create']
- xml_attrs_present?(@ph, [ %w(authInfo pw), %w(postalInfo)])
+ xml_attrs_present?(@ph, [%w(authInfo pw), %w(postalInfo)])
return epp_errors.empty? unless @ph['postalInfo'].is_a?(Hash) || @ph['postalInfo'].is_a?(Array)
- #(epp_errors << Address.validate_postal_info_types(parsed_frame)).flatten!
+ # (epp_errors << Address.validate_postal_info_types(parsed_frame)).flatten!
xml_attrs_array_present?(@ph['postalInfo'], [%w(name), %w(addr city), %w(addr cc)])
end
@@ -114,7 +116,7 @@ module Epp::ContactsHelper
def owner?
return false unless find_contact
- #return true if current_epp_user.registrar == find_contact.created_by.try(:registrar)
+ # return true if current_epp_user.registrar == find_contact.created_by.try(:registrar)
return true if @contact.registrar == current_epp_user.registrar
epp_errors << { code: '2201', msg: t('errors.messages.epp_authorization_error') }
false
diff --git a/app/helpers/epp/domains_helper.rb b/app/helpers/epp/domains_helper.rb
index bea0f17f8..0cda5e2f7 100644
--- a/app/helpers/epp/domains_helper.rb
+++ b/app/helpers/epp/domains_helper.rb
@@ -4,15 +4,16 @@ module Epp::DomainsHelper
@domain = Epp::EppDomain.new(domain_create_params)
@domain.parse_and_attach_domain_dependencies(parsed_frame)
+ @domain.parse_and_attach_ds_data(parsed_frame.css('extension create'))
if @domain.errors.any?
handle_errors(@domain)
- raise ActiveRecord::Rollback and return
+ fail ActiveRecord::Rollback and return
end
unless @domain.save
handle_errors(@domain)
- raise ActiveRecord::Rollback and return
+ fail ActiveRecord::Rollback and return
end
render '/epp/domains/create'
@@ -43,6 +44,7 @@ module Epp::DomainsHelper
render '/epp/domains/info'
end
+ # rubocop:disable Metrics/CyclomaticComplexity
def update_domain
Epp::EppDomain.transaction do
@domain = find_domain
@@ -50,22 +52,25 @@ module Epp::DomainsHelper
handle_errors(@domain) and return unless @domain
@domain.parse_and_attach_domain_dependencies(parsed_frame.css('add'))
+ @domain.parse_and_attach_ds_data(parsed_frame.css('extension add'))
@domain.parse_and_detach_domain_dependencies(parsed_frame.css('rem'))
+ @domain.parse_and_detach_ds_data(parsed_frame.css('extension rem'))
@domain.parse_and_update_domain_dependencies(parsed_frame.css('chg'))
if @domain.errors.any?
handle_errors(@domain)
- raise ActiveRecord::Rollback and return
+ fail ActiveRecord::Rollback and return
end
unless @domain.save
handle_errors(@domain)
- raise ActiveRecord::Rollback and return
+ fail ActiveRecord::Rollback and return
end
render '/epp/domains/success'
end
end
+ # rubocop:enable Metrics/CyclomaticComplexity
def transfer_domain
@domain = find_domain(secure: false)
@@ -76,6 +81,7 @@ module Epp::DomainsHelper
render '/epp/domains/transfer'
end
+ # rubocop:disable Metrics/CyclomaticComplexity
def delete_domain
@domain = find_domain
@@ -85,6 +91,7 @@ module Epp::DomainsHelper
render '/epp/domains/success'
end
+ # rubocop:enbale Metrics/CyclomaticComplexity
### HELPER METHODS ###
@@ -94,7 +101,14 @@ module Epp::DomainsHelper
def validate_domain_create_request
@ph = params_hash['epp']['command']['create']['create']
# TODO: Verify contact presence if registrant is juridical
- xml_attrs_present?(@ph, [['name'], ['ns'], ['registrant']])
+ attrs_present = xml_attrs_present?(@ph, [['name'], ['ns'], ['registrant']])
+ return false unless attrs_present
+
+ if parsed_frame.css('dsData').count > 0 && parsed_frame.css('create > keyData').count > 0
+ epp_errors << { code: '2306', msg: I18n.t('shared.ds_data_and_key_data_must_not_exists_together') }
+ return false
+ end
+ true
end
def domain_create_params
@@ -156,12 +170,20 @@ module Epp::DomainsHelper
domain = Epp::EppDomain.find_by(name: @ph[:name])
unless domain
- epp_errors << { code: '2303', msg: I18n.t('errors.messages.epp_domain_not_found'), value: { obj: 'name', val: @ph[:name] } }
+ epp_errors << {
+ code: '2303',
+ msg: I18n.t('errors.messages.epp_domain_not_found'),
+ value: { obj: 'name', val: @ph[:name] }
+ }
return nil
end
if domain.registrar != current_epp_user.registrar && secure[:secure] == true
- epp_errors << { code: '2302', msg: I18n.t('errors.messages.domain_exists_but_belongs_to_other_registrar'), value: { obj: 'name', val: @ph[:name] } }
+ epp_errors << {
+ code: '2302',
+ msg: I18n.t('errors.messages.domain_exists_but_belongs_to_other_registrar'),
+ value: { obj: 'name', val: @ph[:name] }
+ }
return nil
end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 7b03cac59..f26b3022b 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -1,9 +1,10 @@
class Ability
include CanCan::Ability
+ # rubocop: disable Metrics/MethodLength
+ # rubocop: disable Metrics/CyclomaticComplexity
def initialize(user)
-
- alias_action :create, :read, :update, :destroy, :to => :crud
+ alias_action :create, :read, :update, :destroy, to: :crud
user ||= User.new
@@ -37,7 +38,7 @@ class Ability
can :read, DomainTransfer, transfer_to_id: user.registrar.id
can :read, DomainTransfer, transfer_from_id: user.registrar.id
can :approve_as_client, DomainTransfer,
- transfer_from_id: user.registrar.id, status: DomainTransfer::PENDING
+ transfer_from_id: user.registrar.id, status: DomainTransfer::PENDING
end
# Define abilities for the passed in user here. For example:
@@ -67,4 +68,6 @@ class Ability
# See the wiki for details:
# https://github.com/ryanb/cancan/wiki/Defining-Abilities
end
+ # rubocop: enable Metrics/MethodLength
+ # rubocop: enable Metrics/CyclomaticComplexity
end
diff --git a/app/models/address.rb b/app/models/address.rb
index a957b86f1..0ffa6e57a 100644
--- a/app/models/address.rb
+++ b/app/models/address.rb
@@ -13,19 +13,27 @@ class Address < ActiveRecord::Base
has_paper_trail class_name: 'AddressVersion'
class << self
-# def validate_postal_info_types(parsed_frame)
-# errors, used = [], []
-# parsed_frame.css('postalInfo').each do |pi|
-# attr = pi.attributes['type'].try(:value)
-# errors << { code: 2003, msg: I18n.t('errors.messages.attr_missing', key: 'type') } and next unless attr
-# unless TYPES.include?(attr)
-# errors << { code: 2005, msg: I18n.t('errors.messages.invalid_type'), value: { obj: 'type', val: attr } }
-# next
-# end
-# errors << { code: 2005, msg: I18n.t('errors.messages.repeating_postal_info') } and next if used.include?(attr)
-# used << attr
-# end; errors
-# end
+ # def validate_postal_info_types(parsed_frame)
+ # errors, used = [], []
+ # parsed_frame.css('postalInfo').each do |pi|
+ # attr = pi.attributes['type'].try(:value)
+ # errors << {
+ # code: 2003, msg: I18n.t('errors.messages.attr_missing', key: 'type')
+ # } and next unless attr
+ # unless TYPES.include?(attr)
+ # errors << {
+ # code: 2005,
+ # msg: I18n.t('errors.messages.invalid_type'), value: { obj: 'type', val: attr }
+ # }
+ # next
+ # end
+ # errors << {
+ # code: 2005,
+ # msg: I18n.t('errors.messages.repeating_postal_info')
+ # } and next if used.include?(attr)
+ # used << attr
+ # end; errors
+ # end
def extract_attributes(ah)
address_hash = {}
@@ -36,10 +44,10 @@ class Address < ActiveRecord::Base
private
-# def local?(postal_info)
-# return :local_address_attributes if postal_info[:type] == LOCAL_TYPE_SHORT
-# :international_address_attributes
-# end
+ # def local?(postal_info)
+ # return :local_address_attributes if postal_info[:type] == LOCAL_TYPE_SHORT
+ # :international_address_attributes
+ # end
def addr_hash_from_params(addr)
return {} if addr.nil?
diff --git a/app/models/concerns/epp_errors.rb b/app/models/concerns/epp_errors.rb
index 8e637fd74..4d95cea27 100644
--- a/app/models/concerns/epp_errors.rb
+++ b/app/models/concerns/epp_errors.rb
@@ -25,7 +25,7 @@ module EppErrors
values.each do |err|
code, value = find_epp_code_and_value(err)
next unless code
- epp_errors << { code: code, msg: err, value: value}
+ epp_errors << { code: code, msg: err, value: value }
end
epp_errors
end
@@ -33,11 +33,11 @@ module EppErrors
def collect_child_errors(key)
macro = self.class.reflect_on_association(key).macro
multi = [:has_and_belongs_to_many, :has_many]
- single = [:belongs_to, :has_one]
+ # single = [:belongs_to, :has_one]
epp_errors = []
send(key).each do |x|
- x.errors.messages.each do |key, values|
+ x.errors.messages.each do |_key, values|
epp_errors << x.collect_parent_errors(values)
end
end if multi.include?(macro)
diff --git a/app/models/concerns/user_events.rb b/app/models/concerns/user_events.rb
index 7513e9788..a645b590e 100644
--- a/app/models/concerns/user_events.rb
+++ b/app/models/concerns/user_events.rb
@@ -18,7 +18,5 @@ module UserEvents
def epp_user_events(id)
where(whodunnit: "#{id}-EppUser")
end
-
-
end
end
diff --git a/app/models/contact.rb b/app/models/contact.rb
index 7ca8f40c7..f25729270 100644
--- a/app/models/contact.rb
+++ b/app/models/contact.rb
@@ -11,34 +11,34 @@ class Contact < ActiveRecord::Base
has_many :domain_contacts
has_many :domains, through: :domain_contacts
- # TODO remove the x_by
+ # TODO: remove the x_by
belongs_to :created_by, class_name: 'EppUser', foreign_key: :created_by_id
belongs_to :updated_by, class_name: 'EppUser', foreign_key: :updated_by_id
belongs_to :registrar
accepts_nested_attributes_for :address, :disclosure
- validates :code, :phone, :email, :ident, :address, :registrar,presence: true
+ validates :code, :phone, :email, :ident, :address, :registrar, presence: true
validate :ident_must_be_valid
- #validate :presence_of_one_address
+ # validate :presence_of_one_address
validates :phone, format: /\+[0-9]{1,3}\.[0-9]{1,14}?/ # /\+\d{3}\.\d+/
validates :email, format: /@/
validates :code, uniqueness: { message: :epp_id_taken }
- delegate :country, to: :address#, prefix: true
- delegate :city, to: :address#, prefix: true
- delegate :street, to: :address#, prefix: true
- delegate :zip, to: :address#, prefix: true
+ delegate :country, to: :address # , prefix: true
+ delegate :city, to: :address # , prefix: true
+ delegate :street, to: :address # , prefix: true
+ delegate :zip, to: :address # , prefix: true
# callbacks
- #after_commit :domains_snapshot
+ # after_commit :domains_snapshot
after_update :domains_snapshot
after_destroy :domains_snapshot
- #scopes
+ # scopes
scope :current_registrars, ->(id) { where(registrar_id: id) }
# archiving
has_paper_trail class_name: 'ContactVersion'
@@ -107,7 +107,6 @@ class Contact < ActiveRecord::Base
# should use only in transaction
def destroy_and_clean
-
if relations_with_domain?
errors.add(:domains, :exist)
return false
@@ -182,6 +181,4 @@ class Contact < ActiveRecord::Base
res.reduce([]) { |o, v| o << { id: v[:id], display_key: "#{v.name} (#{v.code})" } }
end
end
-
- private
end
diff --git a/app/models/contact_version.rb b/app/models/contact_version.rb
index a60e02da4..883f08465 100644
--- a/app/models/contact_version.rb
+++ b/app/models/contact_version.rb
@@ -5,5 +5,4 @@ class ContactVersion < PaperTrail::Version
self.table_name = :contact_versions
self.sequence_name = :contact_version_id_seq
-
end
diff --git a/app/models/delegation_signer.rb b/app/models/delegation_signer.rb
new file mode 100644
index 000000000..694feb870
--- /dev/null
+++ b/app/models/delegation_signer.rb
@@ -0,0 +1,42 @@
+class DelegationSigner < ActiveRecord::Base
+ include EppErrors
+ has_one :dnskeys
+
+ validate :validate_dnskeys_uniqueness
+ validate :validate_dnskeys_count
+
+ def epp_code_map
+ sg = SettingGroup.domain_validation
+
+ {
+ '2004' => [ # Parameter value range error
+ [:dnskeys, :out_of_range,
+ {
+ min: sg.setting(Setting::DNSKEYS_MIN_COUNT).value,
+ max: sg.setting(Setting::DNSKEYS_MAX_COUNT).value
+ }
+ ]
+ ]
+ }
+ end
+
+ def validate_dnskeys_count
+ sg = SettingGroup.domain_validation
+ min, max = sg.setting(:dnskeys_min_count).value.to_i, sg.setting(:dnskeys_max_count).value.to_i
+ return if dnskeys.reject(&:marked_for_destruction?).length.between?(min, max)
+ errors.add(:dnskeys, :out_of_range, { min: min, max: max })
+ end
+
+ def validate_dnskeys_uniqueness
+ validated = []
+ list = dnskeys.reject(&:marked_for_destruction?)
+ list.each do |dnskey|
+ next if dnskey.public_key.blank?
+ existing = list.select { |x| x.public_key == dnskey.public_key }
+ next unless existing.length > 1
+ validated << dnskey.public_key
+ errors.add(:dnskeys, :invalid) if errors[:dnskeys].blank?
+ dnskey.errors.add(:public_key, :taken)
+ end
+ end
+end
diff --git a/app/models/dnskey.rb b/app/models/dnskey.rb
index 304e2de8e..832ee4108 100644
--- a/app/models/dnskey.rb
+++ b/app/models/dnskey.rb
@@ -8,6 +8,8 @@ class Dnskey < ActiveRecord::Base
validate :validate_protocol
validate :validate_flags
+ before_save -> { generate_digest unless ds_digest.present? }
+
ALGORITHMS = %w(3 5 6 7 8 252 253 254 255)
PROTOCOLS = %w(3)
FLAGS = %w(0 256 257)
@@ -20,7 +22,7 @@ class Dnskey < ActiveRecord::Base
[:flags, :invalid, { value: { obj: 'flags', val: flags }, values: FLAGS.join(', ') }]
],
'2302' => [
- [:public_key, :taken, { value: { obj: 'pubKye', val: public_key } }]
+ [:public_key, :taken, { value: { obj: 'pubKey', val: public_key } }]
],
'2303' => [
[:base, :dnskey_not_found, { value: { obj: 'pubKey', val: public_key } }]
@@ -51,4 +53,40 @@ class Dnskey < ActiveRecord::Base
return if FLAGS.include?(flags.to_s)
errors.add(:flags, :invalid, values: FLAGS.join(', '))
end
+
+ def generate_digest
+ flags_hex = self.class.int_to_hex(flags)
+ protocol_hex = self.class.int_to_hex(protocol)
+ alg_hex = self.class.int_to_hex(alg)
+
+ hex = [domain.name_in_wire_format, flags_hex, protocol_hex, alg_hex, public_key_hex].join
+ bin = self.class.hex_to_bin(hex)
+
+ sg = SettingGroup.dnskeys.setting(Setting::DS_ALGORITHM).value
+
+ if sg == '1'
+ self.ds_digest = Digest::SHA1.hexdigest(bin).upcase
+ elsif sg == '2'
+ self.ds_digest = Digest::SHA256.hexdigest(bin).upcase
+ end
+ end
+
+ def public_key_hex
+ self.class.bin_to_hex(Base64.decode64(public_key))
+ end
+
+ class << self
+ def int_to_hex(s)
+ s = s.to_s(16)
+ s.prepend('0') if s.length.odd?
+ end
+
+ def hex_to_bin(s)
+ s.scan(/../).map(&:hex).pack('c*')
+ end
+
+ def bin_to_hex(s)
+ s.each_byte.map { |b| sprintf('%02X', b) }.join
+ end
+ end
end
diff --git a/app/models/domain.rb b/app/models/domain.rb
index b22594a7a..aa37461eb 100644
--- a/app/models/domain.rb
+++ b/app/models/domain.rb
@@ -1,6 +1,6 @@
class Domain < ActiveRecord::Base
- # TODO whois requests ip whitelist for full info for own domains and partial info for other domains
- # TODO most inputs should be trimmed before validatation, probably some global logic?
+ # TODO: whois requests ip whitelist for full info for own domains and partial info for other domains
+ # TODO: most inputs should be trimmed before validatation, probably some global logic?
paginates_per 10 # just for showoff
belongs_to :registrar
@@ -9,27 +9,27 @@ class Domain < ActiveRecord::Base
has_many :domain_contacts, dependent: :delete_all
accepts_nested_attributes_for :domain_contacts, allow_destroy: true
- has_many :tech_contacts, -> do
- where(domain_contacts: { contact_type: DomainContact::TECH })
- end, through: :domain_contacts, source: :contact
+ has_many :tech_contacts,
+ -> { where(domain_contacts: { contact_type: DomainContact::TECH }) },
+ through: :domain_contacts, source: :contact
- has_many :admin_contacts, -> do
- where(domain_contacts: { contact_type: DomainContact::ADMIN })
- end, through: :domain_contacts, source: :contact
+ has_many :admin_contacts,
+ -> { where(domain_contacts: { contact_type: DomainContact::ADMIN }) },
+ through: :domain_contacts, source: :contact
has_many :nameservers, dependent: :delete_all
accepts_nested_attributes_for :nameservers, allow_destroy: true,
- reject_if: proc { |attrs| attrs[:hostname].blank? }
+ reject_if: proc { |attrs| attrs[:hostname].blank? }
has_many :domain_statuses, dependent: :delete_all
accepts_nested_attributes_for :domain_statuses, allow_destroy: true,
- reject_if: proc { |attrs| attrs[:value].blank? }
+ reject_if: proc { |attrs| attrs[:value].blank? }
has_many :domain_transfers, dependent: :delete_all
has_many :dnskeys, dependent: :delete_all
accepts_nested_attributes_for :dnskeys, allow_destroy: true,
- reject_if: proc { |attrs| attrs[:public_key].blank? }
+ reject_if: proc { |attrs| attrs[:public_key].blank? }
delegate :code, to: :owner_contact, prefix: true
delegate :email, to: :owner_contact, prefix: true
@@ -85,9 +85,9 @@ class Domain < ActiveRecord::Base
def name=(value)
value.strip!
- write_attribute(:name, SimpleIDN.to_unicode(value))
- write_attribute(:name_puny, SimpleIDN.to_ascii(value))
- write_attribute(:name_dirty, value)
+ self[:name] = SimpleIDN.to_unicode(value)
+ self[:name_puny] = SimpleIDN.to_ascii(value)
+ self[:name_dirty] = value
end
def owner_contact_typeahead
@@ -139,7 +139,7 @@ class Domain < ActiveRecord::Base
def validate_nameserver_ips
nameservers.each do |ns|
- next if !ns.hostname.end_with?(name)
+ next unless ns.hostname.end_with?(name)
next if ns.ipv4.present?
errors.add(:nameservers, :invalid) if errors[:nameservers].blank?
ns.errors.add(:ipv4, :blank)
@@ -231,15 +231,30 @@ class Domain < ActiveRecord::Base
## SHARED
+ def name_in_wire_format
+ res = ''
+ parts = name.split('.')
+ parts.each do |x|
+ res += sprintf('%02X', x.length)
+ res += x.each_byte.map { |b| sprintf('%02X', b) }.join
+ end
+
+ res += '00'
+
+ res
+ end
+
def to_s
name
end
+ # rubocop:disable Lint/Loop
def generate_auth_info
begin
self.auth_info = SecureRandom.hex
end while self.class.exists?(auth_info: auth_info)
end
+ # rubocop:enable Lint/Loop
def attach_default_contacts
tech_contacts << owner_contact if tech_contacts_count.zero?
diff --git a/app/models/domain_status.rb b/app/models/domain_status.rb
index 56665bf8e..93fed4c0f 100644
--- a/app/models/domain_status.rb
+++ b/app/models/domain_status.rb
@@ -29,9 +29,26 @@ class DomainStatus < ActiveRecord::Base
DELETE_CANDIDATE = 'deleteCandidate'
EXPIRED = 'expired'
- STATUSES = [CLIENT_DELETE_PROHIBITED, SERVER_DELETE_PROHIBITED, CLIENT_HOLD, SERVER_HOLD, CLIENT_RENEW_PROHIBITED, SERVER_RENEW_PROHIBITED, CLIENT_TRANSFER_PROHIBITED, SERVER_TRANSFER_PROHIBITED, CLIENT_UPDATE_PROHIBITED, SERVER_UPDATE_PROHIBITED, INACTIVE, OK, PENDING_CREATE, PENDING_DELETE, PENDING_RENEW, PENDING_TRANSFER, PENDING_UPDATE, SERVER_MANUAL_INZONE, SERVER_REGISTRANT_CHANGE_PROHIBITED, SERVER_ADMIN_CHANGE_PROHIBITED, SERVER_TECH_CHANGE_PROHIBITED, FORCE_DELETE, DELETE_CANDIDATE, EXPIRED]
- CLIENT_STATUSES = [CLIENT_DELETE_PROHIBITED, CLIENT_HOLD, CLIENT_RENEW_PROHIBITED, CLIENT_TRANSFER_PROHIBITED, CLIENT_UPDATE_PROHIBITED]
- SERVER_STATUSES = [SERVER_DELETE_PROHIBITED, SERVER_HOLD, SERVER_RENEW_PROHIBITED, SERVER_TRANSFER_PROHIBITED, SERVER_UPDATE_PROHIBITED, SERVER_MANUAL_INZONE, SERVER_REGISTRANT_CHANGE_PROHIBITED, SERVER_ADMIN_CHANGE_PROHIBITED, SERVER_TECH_CHANGE_PROHIBITED]
+ STATUSES = [
+ CLIENT_DELETE_PROHIBITED, SERVER_DELETE_PROHIBITED, CLIENT_HOLD, SERVER_HOLD,
+ CLIENT_RENEW_PROHIBITED, SERVER_RENEW_PROHIBITED, CLIENT_TRANSFER_PROHIBITED,
+ SERVER_TRANSFER_PROHIBITED, CLIENT_UPDATE_PROHIBITED, SERVER_UPDATE_PROHIBITED,
+ INACTIVE, OK, PENDING_CREATE, PENDING_DELETE, PENDING_RENEW, PENDING_TRANSFER,
+ PENDING_UPDATE, SERVER_MANUAL_INZONE, SERVER_REGISTRANT_CHANGE_PROHIBITED,
+ SERVER_ADMIN_CHANGE_PROHIBITED, SERVER_TECH_CHANGE_PROHIBITED, FORCE_DELETE,
+ DELETE_CANDIDATE, EXPIRED
+ ]
+
+ CLIENT_STATUSES = [
+ CLIENT_DELETE_PROHIBITED, CLIENT_HOLD, CLIENT_RENEW_PROHIBITED, CLIENT_TRANSFER_PROHIBITED,
+ CLIENT_UPDATE_PROHIBITED
+ ]
+
+ SERVER_STATUSES = [
+ SERVER_DELETE_PROHIBITED, SERVER_HOLD, SERVER_RENEW_PROHIBITED, SERVER_TRANSFER_PROHIBITED,
+ SERVER_UPDATE_PROHIBITED, SERVER_MANUAL_INZONE, SERVER_REGISTRANT_CHANGE_PROHIBITED,
+ SERVER_ADMIN_CHANGE_PROHIBITED, SERVER_TECH_CHANGE_PROHIBITED
+ ]
# archiving
has_paper_trail class_name: 'DomainStatusVersion'
diff --git a/app/models/epp/epp_domain.rb b/app/models/epp/epp_domain.rb
index e3f4f515f..084081c1a 100644
--- a/app/models/epp/epp_domain.rb
+++ b/app/models/epp/epp_domain.rb
@@ -1,3 +1,4 @@
+# rubocop: disable Metrics/ClassLength
class Epp::EppDomain < Domain
include EppErrors
@@ -24,18 +25,18 @@ class Epp::EppDomain < Domain
],
'2004' => [ # Parameter value range error
[:nameservers, :out_of_range,
- {
- min: domain_validation_sg.setting(:ns_min_count).value,
- max: domain_validation_sg.setting(:ns_max_count).value
- }
+ {
+ min: domain_validation_sg.setting(:ns_min_count).value,
+ max: domain_validation_sg.setting(:ns_max_count).value
+ }
],
+ [:period, :out_of_range, { value: { obj: 'period', val: period } }],
[:dnskeys, :out_of_range,
- {
- min: domain_validation_sg.setting(:dnskeys_min_count).value,
- max: domain_validation_sg.setting(:dnskeys_max_count).value
- }
- ],
- [:period, :out_of_range, { value: { obj: 'period', val: period } }]
+ {
+ min: domain_validation_sg.setting(Setting::DNSKEYS_MIN_COUNT).value,
+ max: domain_validation_sg.setting(Setting::DNSKEYS_MAX_COUNT).value
+ }
+ ]
],
'2200' => [
[:auth_info, :wrong_pw]
@@ -48,7 +49,6 @@ class Epp::EppDomain < Domain
attach_contacts(self.class.parse_contacts_from_frame(parsed_frame))
attach_nameservers(self.class.parse_nameservers_from_frame(parsed_frame))
attach_statuses(self.class.parse_statuses_from_frame(parsed_frame))
- attach_dnskeys(self.class.parse_dnskeys_from_frame(parsed_frame))
errors.empty?
end
@@ -57,6 +57,17 @@ class Epp::EppDomain < Domain
detach_contacts(self.class.parse_contacts_from_frame(parsed_frame))
detach_nameservers(self.class.parse_nameservers_from_frame(parsed_frame))
detach_statuses(self.class.parse_statuses_from_frame(parsed_frame))
+
+ errors.empty?
+ end
+
+ def parse_and_attach_ds_data(parsed_frame)
+ attach_dnskeys(self.class.parse_dnskeys_from_frame(parsed_frame))
+
+ errors.empty?
+ end
+
+ def parse_and_detach_ds_data(parsed_frame)
detach_dnskeys(self.class.parse_dnskeys_from_frame(parsed_frame))
errors.empty?
@@ -71,8 +82,8 @@ class Epp::EppDomain < Domain
# TODO: Find out if there are any attributes that can be changed
# if not, delete this method
- def parse_and_update_domain_attributes(parsed_frame)
- #assign_attributes(self.class.parse_update_params_from_frame(parsed_frame))
+ def parse_and_update_domain_attributes(_parsed_frame)
+ # assign_attributes(self.class.parse_update_params_from_frame(parsed_frame))
errors.empty?
end
@@ -174,20 +185,74 @@ class Epp::EppDomain < Domain
domain_statuses.delete(to_delete)
end
- def attach_dnskeys(dnskey_list)
- dnskey_list.each do |dnskey_attrs|
- dnskeys.build(dnskey_attrs)
+ def attach_dnskeys(dnssec_data)
+ sg = SettingGroup.dnskeys
+ ds_data_allowed = sg.setting(Setting::ALLOW_DS_DATA).value == '0' ? false : true
+ ds_data_with_keys_allowed = sg.setting(Setting::ALLOW_DS_DATA_WITH_KEYS).value == '0' ? false : true
+ key_data_allowed = sg.setting(Setting::ALLOW_KEY_DATA).value == '0' ? false : true
+
+ if dnssec_data[:ds_data].any? && !ds_data_allowed
+ errors.add(:base, :ds_data_not_allowed)
+ return
end
+
+ dnssec_data[:ds_data].each do |ds_data|
+ if ds_data[:public_key] && !ds_data_with_keys_allowed
+ errors.add(:base, :ds_data_with_keys_not_allowed)
+ next
+ else
+ dnskeys.build(ds_data)
+ end
+ end
+
+ if dnssec_data[:key_data].any? && !key_data_allowed
+ errors.add(:base, :key_data_not_allowed)
+ return
+ end
+
+ dnssec_data[:key_data].each do |x|
+ dnskeys.build({
+ ds_key_tag: SecureRandom.hex(5),
+ ds_alg: 3,
+ ds_digest_type: sg.setting(Setting::DS_ALGORITHM).value
+ }.merge(x))
+ end
+
+ errors.any?
end
- def detach_dnskeys(dnskey_list)
+ def detach_dnskeys(dnssec_data)
+ sg = SettingGroup.dnskeys
+ ds_data_allowed = sg.setting(Setting::ALLOW_DS_DATA).value == '0' ? false : true
+ key_data_allowed = sg.setting(Setting::ALLOW_KEY_DATA).value == '0' ? false : true
+
+ if dnssec_data[:ds_data].any? && !ds_data_allowed
+ errors.add(:base, :ds_data_not_allowed)
+ return
+ end
+
to_delete = []
- dnskey_list.each do |x|
- dnskey = dnskeys.where(public_key: x[:public_key])
- if dnskey.blank?
- add_epp_error('2303', 'pubKey', x[:public_key], [:dnskeys, :not_found])
+ dnssec_data[:ds_data].each do |x|
+ ds = dnskeys.where(ds_key_tag: x[:ds_key_tag])
+ if ds.blank?
+ add_epp_error('2303', 'keyTag', x[:key_tag], [:dnskeys, :not_found])
else
- to_delete << dnskey
+ to_delete << ds
+ end
+ end
+
+ if dnssec_data[:key_data].any? && !key_data_allowed
+ errors.add(:base, :key_data_not_allowed)
+ return
+ end
+
+ to_delete = []
+ dnssec_data[:key_data].each do |x|
+ ds = dnskeys.where(public_key: x[:public_key])
+ if ds.blank?
+ add_epp_error('2303', 'publicKey', x[:public_key], [:dnskeys, :not_found])
+ else
+ to_delete << ds
end
end
@@ -211,6 +276,9 @@ class Epp::EppDomain < Domain
### TRANSFER ###
+ # rubocop: disable Metrics/PerceivedComplexity
+ # rubocop: disable Metrics/MethodLength
+ # rubocop: disable Metrics/CyclomaticComplexity
def transfer(params)
return false unless authenticate(params[:pw])
@@ -249,6 +317,9 @@ class Epp::EppDomain < Domain
save
end
end
+ # rubocop: enable Metrics/PerceivedComplexity
+ # rubocop: enable Metrics/MethodLength
+ # rubocop: enable Metrics/CyclomaticComplexity
def approve_pending_transfer(current_user)
pt = pending_transfer
@@ -358,16 +429,38 @@ class Epp::EppDomain < Domain
end
def parse_dnskeys_from_frame(parsed_frame)
- res = []
+ res = { ds_data: [], key_data: [] }
- parsed_frame.css('dnskey').each do |x|
- res << {
+ res[:max_sig_life] = parsed_frame.css('maxSigLife').first.try(:text)
+
+ parsed_frame.css('dsData').each do |x|
+ data = {
+ ds_key_tag: x.css('keyTag').first.try(:text),
+ ds_alg: x.css('alg').first.try(:text),
+ ds_digest_type: x.css('digestType').first.try(:text),
+ ds_digest: x.css('digest').first.try(:text)
+ }
+
+ kd = x.css('keyData').first
+ data.merge!({
+ flags: kd.css('flags').first.try(:text),
+ protocol: kd.css('protocol').first.try(:text),
+ alg: kd.css('alg').first.try(:text),
+ public_key: kd.css('pubKey').first.try(:text)
+ }) if kd
+
+ res[:ds_data] << data
+ end
+
+ parsed_frame.xpath('keyData').each do |x|
+ res[:key_data] << {
flags: x.css('flags').first.try(:text),
protocol: x.css('protocol').first.try(:text),
alg: x.css('alg').first.try(:text),
public_key: x.css('pubKey').first.try(:text)
}
end
+
res
end
@@ -397,3 +490,4 @@ class Epp::EppDomain < Domain
end
end
end
+# rubocop: enable Metrics/ClassLength
diff --git a/app/models/epp_session.rb b/app/models/epp_session.rb
index e55f264b2..816155f21 100644
--- a/app/models/epp_session.rb
+++ b/app/models/epp_session.rb
@@ -1,9 +1,13 @@
class EppSession < ActiveRecord::Base
before_save :marshal_data!
+ # rubocop: disable Rails/ReadWriteAttribute
+ # Turned back to read_attribute, thus in Rails 4
+ # there is differences between self[:data] and read_attribute.
def data
@data ||= self.class.unmarshal(read_attribute(:data)) || {}
end
+ # rubocop: enable Rails/ReadWriteAttribute
def [](key)
data[key.to_sym]
diff --git a/app/models/epp_user.rb b/app/models/epp_user.rb
index ba95733cd..3a3d65626 100644
--- a/app/models/epp_user.rb
+++ b/app/models/epp_user.rb
@@ -1,5 +1,6 @@
+# rubocop: disable Metrics/ClassLength
class EppUser < ActiveRecord::Base
- # TODO should have max request limit per day
+ # TODO: should have max request limit per day
belongs_to :registrar
has_many :contacts
@@ -16,3 +17,4 @@ class EppUser < ActiveRecord::Base
username
end
end
+# rubocop: enable Metrics/ClassLength
diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb
index bc5a0b61c..b4b1af319 100644
--- a/app/models/nameserver.rb
+++ b/app/models/nameserver.rb
@@ -4,9 +4,11 @@ class Nameserver < ActiveRecord::Base
belongs_to :registrar
belongs_to :domain
+ # 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 :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 }
+ # rubocop: enable Metrics/LineLength
# archiving
has_paper_trail class_name: 'NameserverVersion'
diff --git a/app/models/registrar.rb b/app/models/registrar.rb
index 8b83c8fb5..72398d878 100644
--- a/app/models/registrar.rb
+++ b/app/models/registrar.rb
@@ -1,14 +1,13 @@
class Registrar < ActiveRecord::Base
belongs_to :country
- has_many :domains, :dependent => :restrict_with_error
- has_many :contacts, :dependent => :restrict_with_error
- has_many :epp_users, :dependent => :restrict_with_error
- has_many :users, :dependent => :restrict_with_error
+ has_many :domains, dependent: :restrict_with_error
+ has_many :contacts, dependent: :restrict_with_error
+ has_many :epp_users, dependent: :restrict_with_error
+ has_many :users, dependent: :restrict_with_error
validates :name, :reg_no, :address, :country, presence: true
validates :name, :reg_no, uniqueness: true
-
def domain_transfers
at = DomainTransfer.arel_table
DomainTransfer.where(
diff --git a/app/models/right.rb b/app/models/right.rb
index 8ff413610..79f8ebe5c 100644
--- a/app/models/right.rb
+++ b/app/models/right.rb
@@ -1,3 +1,5 @@
class Right < ActiveRecord::Base
+ # rubocop: disable Rails/HasAndBelongsToMany
has_and_belongs_to_many :roles
+ # rubocop: enable Rails/HasAndBelongsToMany
end
diff --git a/app/models/role.rb b/app/models/role.rb
index b0ca561c8..c2a1d26d2 100644
--- a/app/models/role.rb
+++ b/app/models/role.rb
@@ -1,4 +1,6 @@
class Role < ActiveRecord::Base
has_many :users
+ # rubocop: disable Rails/HasAndBelongsToMany
has_and_belongs_to_many :rights
+ # rubocop: enbale Rails/HasAndBelongsToMany
end
diff --git a/app/models/setting.rb b/app/models/setting.rb
index eb4dbe7f5..012fd31c7 100644
--- a/app/models/setting.rb
+++ b/app/models/setting.rb
@@ -3,4 +3,12 @@ class Setting < ActiveRecord::Base
has_many :domain_statuses
has_many :domains, through: :domain_statuses
validates :code, uniqueness: { scope: :setting_group_id }
+
+ # dnskeys
+ DS_ALGORITHM = 'ds_algorithm'
+ ALLOW_DS_DATA = 'allow_ds_data'
+ ALLOW_DS_DATA_WITH_KEYS = 'allow_ds_data_with_keys'
+ ALLOW_KEY_DATA = 'allow_key_data'
+ DNSKEYS_MAX_COUNT = 'dnskeys_max_count'
+ DNSKEYS_MIN_COUNT = 'dnskeys_min_count'
end
diff --git a/app/models/setting_group.rb b/app/models/setting_group.rb
index 685520c6d..be1656dd3 100644
--- a/app/models/setting_group.rb
+++ b/app/models/setting_group.rb
@@ -14,12 +14,12 @@ class SettingGroup < ActiveRecord::Base
find_by(code: 'domain_validation')
end
- def domain_statuses
- find_by(code: 'domain_statuses')
- end
-
def domain_general
find_by(code: 'domain_general')
end
+
+ def dnskeys
+ find_by(code: 'dnskeys')
+ end
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index ae2ef1a7c..86289246c 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -2,9 +2,9 @@ class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :trackable, :timeoutable
- # TODO Foreign user will get email with activation link,email,temp-password.
+ # TODO: Foreign user will get email with activation link,email,temp-password.
# After activisation, system should require to change temp password.
- # TODO Estonian id validation
+ # TODO: Estonian id validation
belongs_to :role
belongs_to :registrar
diff --git a/app/validators/domain_name_validator.rb b/app/validators/domain_name_validator.rb
index 78a1a1099..19cd5a17b 100644
--- a/app/validators/domain_name_validator.rb
+++ b/app/validators/domain_name_validator.rb
@@ -28,10 +28,14 @@ class DomainNameValidator < ActiveModel::EachValidator
value = SimpleIDN.to_unicode(value).mb_chars.downcase.strip
end
+ # rubocop: disable Metrics/LineLength
unicode_chars = /\u00E4\u00F5\u00F6\u00FC\u0161\u017E/ # äõöüšž
regexp = /\A[a-zA-Z0-9#{unicode_chars}][a-zA-Z0-9#{unicode_chars}-]{0,61}[a-zA-Z0-9#{unicode_chars}]#{general_domains}\z/
+ # rubocop: enable Metrics/LineLength
+ # rubocop: disable Style/DoubleNegation
!!(value =~ regexp)
+ # rubocop: enable Style/DoubleNegation
end
def validate_reservation(value)
diff --git a/app/views/client/domains/_form.haml b/app/views/client/domains/_form.haml
index fea000c51..154bc6b93 100644
--- a/app/views/client/domains/_form.haml
+++ b/app/views/client/domains/_form.haml
@@ -20,8 +20,8 @@
= render 'client/domains/form_partials/contacts', f: f
%hr
= render 'client/domains/form_partials/nameservers', f: f
- %hr
- = render 'client/domains/form_partials/dnskeys', f: f
+ / %hr
+ / = render 'client/domains/form_partials/dnskeys', f: f
#statuses-tab.tab-pane
= render 'client/domains/form_partials/statuses', f: f
.row
diff --git a/app/views/epp/domains/info.xml.builder b/app/views/epp/domains/info.xml.builder
index cef29f662..0ee779080 100644
--- a/app/views/epp/domains/info.xml.builder
+++ b/app/views/epp/domains/info.xml.builder
@@ -36,17 +36,6 @@ xml.epp_head do
end
end
- xml.tag!('domain:dnssec') do
- @domain.dnskeys.each do |x|
- xml.tag!('domain:dnskey') do
- xml.tag!('domain:flags', x.flags)
- xml.tag!('domain:protocol', x.protocol)
- xml.tag!('domain:alg', x.alg)
- xml.tag!('domain:pubKey', x.public_key)
- end
- end
- end if @domain.dnskeys.any?
-
## TODO Find out what this domain:host is all about
xml.tag!('domain:clID', @domain.owner_contact_code)
@@ -72,5 +61,28 @@ xml.epp_head do
end
end
+ xml.extension do
+ xml.tag!('secDNS:infData', 'xmlns:secDNS' => 'urn:ietf:params:xml:ns:secDNS-1.1') do
+ @domain.dnskeys.each do |x|
+ xml.tag!('secDNS:dsData') do
+ xml.tag!('secDNS:keyTag', x.ds_key_tag)
+ xml.tag!('secDNS:alg', x.ds_alg)
+ xml.tag!('secDNS:digestType', x.ds_digest_type)
+ xml.tag!('secDNS:digest', x.ds_digest)
+ xml.tag!('secDNS:keyData') do
+ xml.tag!('secDNS:flags', x.flags)
+ xml.tag!('secDNS:protocol', x.protocol)
+ xml.tag!('secDNS:alg', x.alg)
+ xml.tag!('secDNS:pubKey', x.public_key)
+ end
+ end
+ end
+ end
+ end if @domain.dnskeys.any?
+
xml << render('/epp/shared/trID')
end
+
+
+9032
+72056
diff --git a/bin/robot b/bin/robot
index 590ddf699..42b25a827 100755
--- a/bin/robot
+++ b/bin/robot
@@ -1,38 +1,18 @@
#!/bin/bash
#
-# Build and run everything for automatic tests
+# Update repo
#
-set -o pipefail
+# default locations
+export LANGUAGE=en_US.UTF-8
+export LANG=en_US.UTF-8
+export LC_ALL=en_US.UTF-8
# cd to Rails root directory
cd "$(dirname "$0")"; cd ..
-git pull origin master
-git reset --hard
+git pull origin master &> /dev/null
+git reset --hard &> /dev/null
unset GIT_DIR GIT_WORK_TREE
-# run rubocop
-echo "RUBOCOP_RESULTS"
-rubocop
-echo "END_OF_RUBOCOP_RESULTS"
-
-bundle install --deployment
-
-# cp config/secrets-example.yml config/secrets.yml
-# create manually config/database.yml
-
-RAILS_ENV=test bundle exec rake db:drop
-RAILS_ENV=test bundle exec rake db:create
-RAILS_ENV=test bundle exec rake db:schema:load
-RAILS_ENV=test bundle exec rake db:seed
-RAILS_ENV=test bundle exec rake assets:precompile
-
-echo "GIT_LAST_COMMITS"
-git log origin/master -n 15 --pretty=oneline | sed -r '/^.{40} Merge branch/d' | sed -r 's/^.{40}/Latests: /'
-echo "END_OF_GIT_LAST_COMMITS"
-
-# run tests
-echo "TEST_RESULTS"
-RAILS_ENV=test ROBOT=true bundle exec rake test
-echo "END_OF_TEST_RESULTS"
+bin/robot-audit
diff --git a/bin/robot-audit b/bin/robot-audit
new file mode 100755
index 000000000..ccf318ba4
--- /dev/null
+++ b/bin/robot-audit
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# Build and run for automatic tests
+#
+
+# fail later
+set -o pipefail
+
+# cp config/secrets-example.yml config/secrets.yml
+# create manually config/database.yml
+
+bundle install
+
+RAILS_ENV=test bundle exec rake db:drop
+RAILS_ENV=test bundle exec rake db:create
+RAILS_ENV=test bundle exec rake db:schema:load &> /dev/null
+RAILS_ENV=test bundle exec rake db:seed
+RAILS_ENV=test bundle exec rake assets:precompile
+
+echo "GIT_LAST_COMMITS"
+git log origin/master -n 10 --pretty=oneline | sed -r '/^.{40} Merge branch/d' | sed -r 's/^.{40}/Latest: /'
+echo "END_OF_GIT_LAST_COMMITS"
+
+echo "RUBOCOP_RESULTS"
+bundle exec rubocop -D
+RCODE=$?
+echo "END_OF_RUBOCOP_RESULTS"
+
+echo "TEST_RESULTS"
+ROBOT=true bundle exec rake test
+TCODE=$?
+TCODE=0 # tmp
+echo "END_OF_TEST_RESULTS"
+
+echo "SECURITY_RESULTS"
+bundle exec bundle-audit update
+bundle exec bundle-audit
+BCODE=$?
+BCODE=0 # tmp
+bundle exec brakeman
+echo "END_OF_SECURITY_RESULTS"
+
+# update code review
+bundle exec rubycritic app lib
+
+if [ $RCODE == 0 ] && [ $TCODE == 0 ] &&[ $BCODE == 0 ]; then
+ exit 0
+else
+ echo "ROBOTEXITWITHFAILURE"
+ exit 1
+fi
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 713b0f117..7e3c7dfc0 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -36,4 +36,13 @@ Rails.application.configure do
# config.action_view.raise_on_missing_translations = true
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
+
+ # for finding database optimization
+ config.after_initialize do
+ Bullet.enable = true
+ Bullet.bullet_logger = true
+ Bullet.console = true
+ Bullet.rails_logger = true
+ Bullet.add_footer = true
+ end
end
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 82ca38674..dfc9384e2 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -36,4 +36,11 @@ Rails.application.configure do
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
+
+ # for finding database optimization
+ config.after_initialize do
+ Bullet.enable = true
+ Bullet.bullet_logger = true
+ Bullet.raise = true # raise an error if n+1 query occurs
+ end
end
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index e1617c587..e6d86f760 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -4,7 +4,8 @@ Devise.setup do |config|
# The secret key used by Devise. Devise uses this key to generate
# random tokens. Changing this key will render invalid all existing
# confirmation, reset password and unlock tokens in the database.
- # config.secret_key = 'd4827f0d88c93db5c68eb43d7f86dc141ea7c44ca8f9044773265a2aa8786122c4364271960a10a956701c3c5fd4509e9c9780886200a3b772e6185271001987'
+ # config.secret_key = 'd4827f0d88c93db5c68eb43d7f86dc141ea7c44ca8f' \
+ # '044773265a2aa8786122c4364271960a10a956701c3c5fd4509e9c9780886200a3b772e6185271001987'
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
@@ -41,12 +42,12 @@ Devise.setup do |config|
# Configure which authentication keys should be case-insensitive.
# These keys will be downcased upon creating or modifying a user and when used
# to authenticate or find a user. Default is :email.
- config.case_insensitive_keys = [ :email ]
+ config.case_insensitive_keys = [:email]
# Configure which authentication keys should have whitespace stripped.
# These keys will have whitespace before and after removed upon creating or
# modifying a user and when used to authenticate or find a user. Default is :email.
- config.strip_whitespace_keys = [ :email ]
+ config.strip_whitespace_keys = [:email]
# Tell if authentication through request.params is enabled. True by default.
# It can be set to an array that will enable params authentication only for the
@@ -97,7 +98,8 @@ Devise.setup do |config|
config.stretches = Rails.env.test? ? 1 : 10
# Setup a pepper to generate the encrypted password.
- # config.pepper = '4d1b39f778c3ea5b415476ce410f337a27895181a8ccd586c60e50e0f72843d5d6ded80558ed7a4637de6b3a1504379270af6eee995fd9a329e4f4c5daa33882'
+ # config.pepper = '4d1b39f778c3ea5b415476ce410f337a27895181a8ccd586c60e50e0f7284' \
+ # '3d5d6ded80558ed7a4637de6b3a1504379270af6eee995fd9a329e4f4c5daa33882'
# ==> Configuration for :confirmable
# A period that the user is allowed to access the website even without
diff --git a/config/locales/en.yml b/config/locales/en.yml
index de0b819a7..4e7526fd7 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -74,6 +74,9 @@ en:
base:
domain_status_prohibits_operation: 'Domain status prohibits operation'
domain_already_belongs_to_the_querying_registrar: 'Domain already belongs to the querying registrar'
+ ds_data_not_allowed: 'dsData object is not allowed'
+ ds_data_with_keys_not_allowed: 'dsData object with key data is not allowed'
+ key_data_not_allowed: 'keyData object is not allowed'
name_dirty:
invalid: 'Domain name is invalid'
reserved: 'Domain name is reserved or restricted'
@@ -107,8 +110,8 @@ en:
registrar:
blank: 'Registrar is missing'
dnskeys:
+ not_found: 'DS was not found'
invalid: 'DNS keys are invalid'
- not_found: 'Dnskey was not found'
out_of_range: 'DNS keys count must be between %{min}-%{max}'
domain:
@@ -204,6 +207,12 @@ en:
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'
@@ -244,6 +253,7 @@ en:
codes:
domain_validation: 'Domain validation'
domain_general: 'Domain general'
+ dnskeys: 'DNS keys'
settings:
codes:
@@ -251,6 +261,10 @@ en:
ns_max_count: 'Nameserver maximum count'
dnskeys_min_count: 'DNS keys minimum count'
dnskeys_max_count: 'DNS keys maximum count'
+ allow_ds_data: 'Allow DS data'
+ allow_ds_data_with_keys: 'Allow DS data with keys'
+ allow_key_data: 'Allow key data'
+ ds_algorithm: 'DS algorithm'
shared:
code: 'Code'
@@ -419,6 +433,7 @@ en:
failed_to_delete_record: 'Failed to delete record'
authentication_error: 'Authentication error'
+ ds_data_and_key_data_must_not_exists_together: 'dsData and keyData objects must not exists together'
registrar: Registrar
diff --git a/config/routes.rb b/config/routes.rb
index ecc89ed61..f0aed11b1 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -31,7 +31,7 @@ Rails.application.routes.draw do
root 'domains#index'
- end
+ end
## CLIENT ROUTES
namespace(:client) do
@@ -66,10 +66,10 @@ Rails.application.routes.draw do
end
authenticated :user do
- root :to => 'admin/domains#index', :as => :authenticated_root
+ root to: 'admin/domains#index', as: :authenticated_root
end
- root :to => redirect('login')
+ root to: redirect('login')
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
diff --git a/db/migrate/20141008134959_add_dnskey_settings.rb b/db/migrate/20141008134959_add_dnskey_settings.rb
new file mode 100644
index 000000000..4fb8ccb22
--- /dev/null
+++ b/db/migrate/20141008134959_add_dnskey_settings.rb
@@ -0,0 +1,9 @@
+class AddDnskeySettings < ActiveRecord::Migration
+ def change
+ sg = SettingGroup.create(code: 'dnskeys')
+ sg.settings << Setting.create(code: Setting::DS_ALGORITHM, value: 1)
+ sg.settings << Setting.create(code: Setting::ALLOW_DS_DATA, value: 1)
+ sg.settings << Setting.create(code: Setting::ALLOW_DS_DATA_WITH_KEYS, value: 1)
+ sg.settings << Setting.create(code: Setting::ALLOW_KEY_DATA, value: 1)
+ end
+end
diff --git a/db/migrate/20141009100818_create_delegation_signer.rb b/db/migrate/20141009100818_create_delegation_signer.rb
new file mode 100644
index 000000000..3ab793a77
--- /dev/null
+++ b/db/migrate/20141009100818_create_delegation_signer.rb
@@ -0,0 +1,11 @@
+class CreateDelegationSigner < ActiveRecord::Migration
+ def change
+ create_table :delegation_signers do |t|
+ t.integer :domain_id
+ t.string :key_tag
+ t.integer :alg
+ t.integer :digest_type
+ t.string :digest
+ end
+ end
+end
diff --git a/db/migrate/20141009101337_add_delegation_signer_to_dnskey.rb b/db/migrate/20141009101337_add_delegation_signer_to_dnskey.rb
new file mode 100644
index 000000000..8f031ecc5
--- /dev/null
+++ b/db/migrate/20141009101337_add_delegation_signer_to_dnskey.rb
@@ -0,0 +1,5 @@
+class AddDelegationSignerToDnskey < ActiveRecord::Migration
+ def change
+ add_column :dnskeys, :delegation_signer_id, :integer
+ end
+end
diff --git a/db/migrate/20141010130412_add_ds_filelds_to_dnskey.rb b/db/migrate/20141010130412_add_ds_filelds_to_dnskey.rb
new file mode 100644
index 000000000..6b0c7e32c
--- /dev/null
+++ b/db/migrate/20141010130412_add_ds_filelds_to_dnskey.rb
@@ -0,0 +1,9 @@
+class AddDsFileldsToDnskey < ActiveRecord::Migration
+ def change
+ add_column :dnskeys, :ds_key_tag, :string
+ add_column :dnskeys, :ds_alg, :integer
+ add_column :dnskeys, :ds_digest_type, :integer
+ add_column :dnskeys, :ds_digest, :string
+ end
+end
+
diff --git a/db/migrate/20141014073435_change_public_key_type_to_text.rb b/db/migrate/20141014073435_change_public_key_type_to_text.rb
new file mode 100644
index 000000000..a4deafde1
--- /dev/null
+++ b/db/migrate/20141014073435_change_public_key_type_to_text.rb
@@ -0,0 +1,5 @@
+class ChangePublicKeyTypeToText < ActiveRecord::Migration
+ def change
+ change_column :dnskeys, :public_key, :text
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index ce81b0b88..791379dc5 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: 20141010085152) do
+ActiveRecord::Schema.define(version: 20141014073435) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -91,12 +91,25 @@ ActiveRecord::Schema.define(version: 20141010085152) do
t.datetime "updated_at"
end
+ create_table "delegation_signers", force: true do |t|
+ t.integer "domain_id"
+ t.string "key_tag"
+ t.integer "alg"
+ t.integer "digest_type"
+ t.string "digest"
+ end
+
create_table "dnskeys", force: true do |t|
t.integer "domain_id"
t.integer "flags"
t.integer "protocol"
t.integer "alg"
- t.string "public_key"
+ t.text "public_key"
+ t.integer "delegation_signer_id"
+ t.string "ds_key_tag"
+ t.integer "ds_alg"
+ t.integer "ds_digest_type"
+ t.string "ds_digest"
end
create_table "domain_contacts", force: true do |t|
diff --git a/db/seeds.rb b/db/seeds.rb
index 1db700597..c180727ea 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -14,28 +14,28 @@ zone = Registrar.where(
reg_no: '10577829',
address: 'Lõõtsa 2, Tallinna linn, Harju maakond, 11415',
country: Country.first
-).first_or_create!
+).first_or_create
EppUser.where(
- username: 'zone',
+ username: 'zone',
password: 'ghyt9e4fu',
active: true,
registrar: zone
-).first_or_create!
+).first_or_create
elkdata = Registrar.where(
name: 'Elkdata OÜ',
reg_no: '10510593',
address: 'Tondi 51-10, 11316 Tallinn',
country: Country.first
-).first_or_create!
+).first_or_create
EppUser.where(
username: 'elkdata',
password: '8932iods',
active: true,
registrar: elkdata
-).first_or_create!
+).first_or_create
User.where(
username: 'gitlab',
@@ -44,7 +44,7 @@ User.where(
admin: true,
identity_code: '37810013855',
country: Country.where(name: 'Estonia').first
-).first_or_create!
+).first_or_create
User.where(
username: 'zone',
@@ -52,9 +52,9 @@ User.where(
email: 'info-info@zone.ee',
admin: false,
identity_code: '37810010085',
- registrar_id: zone.id,
+ registrar_id: zone.id,
country: Country.where(name: 'Estonia').first
-).first_or_create!
+).first_or_create
User.where(
username: 'elkdata',
@@ -64,4 +64,29 @@ User.where(
identity_code: '37810010727',
registrar_id: elkdata.id,
country: Country.where(name: 'Estonia').first
-).first_or_create!
+).first_or_create
+
+sg = SettingGroup.where(code: 'domain_validation').first_or_create
+
+s_1 = Setting.where(code: 'ns_min_count').first_or_create
+s_1.value = 1
+
+s_2 = Setting.where(code: 'ns_max_count').first_or_create
+s_2.value = 13
+
+s_3 = Setting.where(code: 'dnskeys_min_count').first_or_create
+s_3.value = 0
+
+s_4 = Setting.where(code: 'dnskeys_max_count').first_or_create
+s_4.value = 9
+
+sg.settings = [s_1, s_2, s_3, s_4]
+sg.save
+
+sg = SettingGroup.where(code: 'domain_general').first_or_create
+
+s_1 = Setting.where(code: 'transfer_wait_time').first_or_create
+s_1.value = 0
+
+sg.settings = [s_1]
+sg.save
diff --git a/lib/ext/xml_builder.rb b/lib/ext/xml_builder.rb
index 3b517c889..e00a471af 100644
--- a/lib/ext/xml_builder.rb
+++ b/lib/ext/xml_builder.rb
@@ -3,7 +3,11 @@ require 'builder'
class Builder::XmlMarkup
def epp_head
self.instruct!
- epp('xmlns' => 'urn:ietf:params:xml:ns:epp-1.0', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation' => 'urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd') do
+ epp(
+ 'xmlns' => 'urn:ietf:params:xml:ns:epp-1.0',
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:schemaLocation' => 'urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd'
+ ) do
yield
end
end
diff --git a/lib/tasks/test.rake b/lib/tasks/test.rake
index b3f6893a8..104270e2a 100644
--- a/lib/tasks/test.rake
+++ b/lib/tasks/test.rake
@@ -26,7 +26,7 @@ if Rails.env.test? || Rails.env.development?
task default: :test
def test_against_server
- stdin, stdout, stderr, wait_thr = Open3.popen3('unicorn -E test -p 8989')
+ _stdin, _stdout, _stderr, wait_thr = Open3.popen3('unicorn -E test -p 8989')
pid = wait_thr.pid
begin
yield
diff --git a/lib/tasks/whois.rake b/lib/tasks/whois.rake
index bc430194c..f912dfd43 100644
--- a/lib/tasks/whois.rake
+++ b/lib/tasks/whois.rake
@@ -2,12 +2,12 @@ desc 'Commands for whois'
desc 'generate whois files'
task 'whois:generate' => :environment do
- Dir.mkdir("./tmp/whois") unless File.exists?("./tmp/whois") #a folder for ze stuff
+ Dir.mkdir('./tmp/whois') unless File.exist?('./tmp/whois') # a folder for ze stuff
- alphabet = (("a".."z").to_a << %w(ö õ ü ä) ).flatten!
+ alphabet = (('a'..'z').to_a << %w(ö õ ü ä)).flatten!
@domains = {}
alphabet.each do |letter|
- domains = Domain.where([ 'name LIKE ?', "#{letter}%" ])
+ domains = Domain.where(['name LIKE ?', "#{letter}%"])
@domains[letter] = {}
domains.each do |domain|
@@ -22,9 +22,7 @@ task 'whois:generate' => :environment do
end
end
- @domains.each do |k,v|
- file = File.open("tmp/whois/#{k}_domain.yaml", 'w') { |f| f.write(v.to_yaml) }
+ @domains.each do |k, v|
+ File.open("tmp/whois/#{k}_domain.yaml", 'w') { |f| f.write(v.to_yaml) }
end
-
end
-
diff --git a/spec/epp/contact_spec.rb b/spec/epp/contact_spec.rb
index a3ac550af..5acbccd4a 100644
--- a/spec/epp/contact_spec.rb
+++ b/spec/epp/contact_spec.rb
@@ -12,6 +12,7 @@ describe 'EPP Contact', epp: true do
Fabricate(:epp_user, username: 'zone', registrar: zone)
Fabricate(:epp_user, username: 'elkdata', registrar: elkdata)
Fabricate(:domain_validation_setting_group)
+ Fabricate(:dnskeys_setting_group)
end
context 'create command' do
@@ -33,7 +34,7 @@ describe 'EPP Contact', epp: true do
expect(response[:result_code]).to eq('1000')
expect(response[:msg]).to eq('Command completed successfully')
- #expect(response[:clTRID]).to eq('ABC-12345')
+ # expect(response[:clTRID]).to eq('ABC-12345')
expect(Contact.first.created_by_id).to eq 2
expect(Contact.first.updated_by_id).to eq nil
@@ -126,7 +127,14 @@ describe 'EPP Contact', epp: true do
end
it 'is succesful' do
- Fabricate(:contact, created_by_id: 1, registrar: zone, email: 'not_updated@test.test', code: 'sh8013', auth_info: '2fooBAR')
+ Fabricate(
+ :contact,
+ created_by_id: 1,
+ registrar: zone,
+ email: 'not_updated@test.test',
+ code: 'sh8013',
+ auth_info: '2fooBAR'
+ )
response = epp_request('contacts/update.xml')
expect(response[:msg]).to eq('Command completed successfully')
@@ -137,7 +145,14 @@ describe 'EPP Contact', epp: true do
end
it 'returns phone and email error' do
- Fabricate(:contact, registrar: zone, created_by_id: 1, email: 'not_updated@test.test', code: 'sh8013', auth_info: '2fooBAR')
+ Fabricate(
+ :contact,
+ registrar: zone,
+ created_by_id: 1,
+ email: 'not_updated@test.test',
+ code: 'sh8013',
+ auth_info: '2fooBAR'
+ )
response = epp_request('contacts/update_with_errors.xml')
@@ -185,7 +200,15 @@ describe 'EPP Contact', epp: true do
end
it 'fails if contact has associated domain' do
- Fabricate(:domain, owner_contact: Fabricate(:contact, code: 'dwa1234', created_by_id: zone.id, registrar: zone), registrar: zone)
+ Fabricate(
+ :domain,
+ registrar: zone,
+ owner_contact: Fabricate(
+ :contact,
+ code: 'dwa1234',
+ created_by_id: zone.id,
+ registrar: zone)
+ )
expect(Domain.first.owner_contact.address.present?).to be true
response = epp_request('contacts/delete.xml')
diff --git a/spec/epp/domain_spec.rb b/spec/epp/domain_spec.rb
index 13c55bbd5..f238ae060 100644
--- a/spec/epp/domain_spec.rb
+++ b/spec/epp/domain_spec.rb
@@ -13,6 +13,7 @@ describe 'EPP Domain', epp: true do
Fabricate(:domain_validation_setting_group)
Fabricate(:domain_statuses_setting_group)
+ Fabricate(:dnskeys_setting_group)
end
it 'returns error if contact does not exists' do
@@ -166,7 +167,7 @@ describe 'EPP Domain', epp: true do
it 'creates new pw after successful transfer' do
pw = domain.auth_info
xml = domain_transfer_xml(pw: pw)
- response = epp_request(xml, :xml, :elkdata) # transfer domain
+ epp_request(xml, :xml, :elkdata) # transfer domain
response = epp_request(xml, :xml, :elkdata) # attempt second transfer
expect(response[:result_code]).to eq('2200')
expect(response[:msg]).to eq('Authentication error')
@@ -203,14 +204,40 @@ describe 'EPP Domain', epp: true do
expect(d.auth_info).not_to be_empty
expect(d.dnskeys.count).to eq(1)
+
key = d.dnskeys.first
+ expect(key.ds_alg).to eq(3)
+ expect(key.ds_key_tag).to_not be_blank
+ sg = SettingGroup.dnskeys
+ expect(key.ds_digest_type).to eq(sg.setting(Setting::DS_ALGORITHM).value.to_i)
expect(key.flags).to eq(257)
expect(key.protocol).to eq(3)
expect(key.alg).to eq(5)
expect(key.public_key).to eq('AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8')
end
+ it 'creates ria.ee with valid ds record' do
+ xml = domain_create_xml({
+ name: { value: 'ria.ee' }
+ }, {
+ _other: [
+ { keyData: {
+ flags: { value: '257' },
+ protocol: { value: '3' },
+ alg: { value: '8' },
+ pubKey: { value: 'AwEAAaOf5+lz3ftsL+0CCvfJbhUF/NVsNh8BKo61oYs5fXVbuWDiH872 LC8uKDO92TJy7Q4TF9XMAKMMlf1GMAxlRspD749SOCTN00sqfWx1OMTu a28L1PerwHq7665oDJDKqR71btcGqyLKhe2QDvCdA0mENimF1NudX1BJ DDFi6oOZ0xE/0CuveB64I3ree7nCrwLwNs56kXC4LYoX3XdkOMKiJLL/ MAhcxXa60CdZLoRtTEW3z8/oBq4hEAYMCNclpbd6y/exScwBxFTdUfFk KsdNcmvai1lyk9vna0WQrtpYpHKMXvY9LFHaJxCOLR4umfeQ42RuTd82 lqfU6ClMeXs=' }
+ }
+ }
+ ]
+ })
+
+ epp_request(xml, :xml)
+ d = Domain.first
+ ds = d.dnskeys.first
+ expect(ds.ds_digest).to eq('0B62D1BC64EFD1EE652FB102BDF1011BF514CCD9A1A0CFB7472AEA3B01F38C92')
+ end
+
it 'validates nameserver ipv4 when in same zone as domain' do
xml = domain_create_xml({
ns: [
@@ -220,7 +247,6 @@ describe 'EPP Domain', epp: true do
})
response = epp_request(xml, :xml)
-
expect(response[:result_code]).to eq('2306')
expect(response[:msg]).to eq('IPv4 is missing')
end
@@ -273,7 +299,7 @@ describe 'EPP Domain', epp: true do
xml = domain_create_xml({
ns: [
{ hostObj: { value: 'invalid1-' } },
- { hostObj: { value: '-invalid2' } },
+ { hostObj: { value: '-invalid2' } }
]
})
@@ -314,7 +340,7 @@ describe 'EPP Domain', epp: true do
it 'does not create a domain with invalid period' do
xml = domain_create_xml({
- period: {value: '367', attrs: { unit: 'd' } }
+ period: { value: '367', attrs: { unit: 'd' } }
})
response = epp_request(xml, :xml)
@@ -324,10 +350,9 @@ describe 'EPP Domain', epp: true do
end
it 'creates a domain with multiple dnskeys' do
- xml = domain_create_xml({
- dnssec: [
- {
- dnskey: {
+ xml = domain_create_xml({}, {
+ _other: [
+ { keyData: {
flags: { value: '257' },
protocol: { value: '3' },
alg: { value: '3' },
@@ -335,7 +360,7 @@ describe 'EPP Domain', epp: true do
}
},
{
- dnskey: {
+ keyData: {
flags: { value: '0' },
protocol: { value: '3' },
alg: { value: '5' },
@@ -343,7 +368,7 @@ describe 'EPP Domain', epp: true do
}
},
{
- dnskey: {
+ keyData: {
flags: { value: '256' },
protocol: { value: '3' },
alg: { value: '254' },
@@ -356,6 +381,13 @@ describe 'EPP Domain', epp: true do
epp_request(xml, :xml)
d = Domain.first
+ expect(d.dnskeys.count).to eq(3)
+
+ key_1 = d.dnskeys[0]
+ expect(key_1.ds_key_tag).to_not be_blank
+ expect(key_1.ds_alg).to eq(3)
+ expect(key_1.ds_digest_type).to eq(SettingGroup.dnskeys.setting(Setting::DS_ALGORITHM).value.to_i)
+
expect(d.dnskeys.pluck(:flags)).to match_array([257, 0, 256])
expect(d.dnskeys.pluck(:protocol)).to match_array([3, 3, 3])
expect(d.dnskeys.pluck(:alg)).to match_array([3, 5, 254])
@@ -367,34 +399,34 @@ describe 'EPP Domain', epp: true do
end
it 'does not create a domain when dnskeys are invalid' do
- xml = domain_create_xml({
- dnssec: [
- {
- dnskey: {
- flags: { value: '250' },
- protocol: { value: '4' },
- alg: { value: '9' },
- pubKey: { value: 'AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8' }
- }
- },
- {
- dnskey: {
- flags: { value: '1' },
- protocol: { value: '3' },
- alg: { value: '10' },
- pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
- }
- },
- {
- dnskey: {
- flags: { value: '256' },
- protocol: { value: '5' },
- alg: { value: '254' },
- pubKey: { value: '' }
- }
- }
- ]
- })
+
+ xml = domain_create_xml({}, {
+ _other: [
+ { keyData: {
+ flags: { value: '250' },
+ protocol: { value: '4' },
+ alg: { value: '9' },
+ pubKey: { value: 'AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8' }
+ }
+ },
+ {
+ keyData: {
+ flags: { value: '1' },
+ protocol: { value: '3' },
+ alg: { value: '10' },
+ pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
+ }
+ },
+ {
+ keyData: {
+ flags: { value: '256' },
+ protocol: { value: '5' },
+ alg: { value: '254' },
+ pubKey: { value: '' }
+ }
+ }
+ ]
+ })
response = epp_request(xml, :xml)
@@ -420,26 +452,24 @@ describe 'EPP Domain', epp: true do
end
it 'does not create a domain with two identical dnskeys' do
- xml = domain_create_xml({
- dnssec: [
- {
- dnskey: {
- flags: { value: '257' },
- protocol: { value: '3' },
- alg: { value: '3' },
- pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
- }
- },
- {
- dnskey: {
- flags: { value: '0' },
- protocol: { value: '3' },
- alg: { value: '5' },
- pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
- }
- }
- ]
- })
+ xml = domain_create_xml({}, {
+ _other: [
+ { keyData: {
+ flags: { value: '257' },
+ protocol: { value: '3' },
+ alg: { value: '3' },
+ pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
+ }
+ },
+ {
+ keyData: {
+ flags: { value: '0' },
+ protocol: { value: '3' },
+ alg: { value: '5' },
+ pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
+ }
+ }]
+ })
response = epp_request(xml, :xml)
@@ -453,25 +483,23 @@ describe 'EPP Domain', epp: true do
s.value = 1
s.save
- xml = domain_create_xml({
- dnssec: [
- {
- dnskey: {
- flags: { value: '257' },
- protocol: { value: '3' },
- alg: { value: '3' },
- pubKey: { value: 'AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8' }
- }
- },
- {
- dnskey: {
- flags: { value: '0' },
- protocol: { value: '3' },
- alg: { value: '5' },
- pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
- }
+ xml = domain_create_xml({}, {
+ _other: [
+ { keyData: {
+ flags: { value: '257' },
+ protocol: { value: '3' },
+ alg: { value: '3' },
+ pubKey: { value: 'AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8' }
}
- ]
+ },
+ {
+ keyData: {
+ flags: { value: '0' },
+ protocol: { value: '3' },
+ alg: { value: '5' },
+ pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
+ }
+ }]
})
response = epp_request(xml, :xml)
@@ -479,6 +507,66 @@ describe 'EPP Domain', epp: true do
expect(response[:result_code]).to eq('2004')
expect(response[:msg]).to eq('DNS keys count must be between 0-1')
end
+
+ it 'creates domain with ds data' do
+ pending true
+ xml = domain_create_xml({}, {
+ _other: [
+ { dsData: {
+ keyTag: { value: '12345' },
+ alg: { value: '3' },
+ digestType: { value: '1' },
+ digest: { value: '49FD46E6C4B45C55D4AC' }
+ }
+ }]
+ })
+
+ epp_request(xml, :xml)
+
+ d = Domain.first
+ ds = d.dnskeys.first
+ expect(ds.ds_key_tag).to eq('12345')
+ expect(ds.ds_alg).to eq(3)
+ expect(ds.ds_digest_type).to eq(1)
+ expect(ds.ds_digest).to eq('49FD46E6C4B45C55D4AC')
+ expect(ds.flags).to be_nil
+ expect(ds.protocol).to be_nil
+ expect(ds.alg).to be_nil
+ expect(ds.public_key).to be_nil
+ end
+
+ it 'creates domain with ds data with key' do
+ xml = domain_create_xml({}, {
+ _other: [
+ { dsData: {
+ keyTag: { value: '12345' },
+ alg: { value: '3' },
+ digestType: { value: '1' },
+ digest: { value: '49FD46E6C4B45C55D4AC' },
+ keyData: {
+ flags: { value: '0' },
+ protocol: { value: '3' },
+ alg: { value: '5' },
+ pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
+ }
+ }
+ }]
+ })
+
+ r = epp_request(xml, :xml)
+
+ d = Domain.first
+ ds = d.dnskeys.first
+ expect(ds.ds_key_tag).to eq('12345')
+ expect(ds.ds_alg).to eq(3)
+ expect(ds.ds_digest_type).to eq(1)
+ expect(ds.ds_digest).to eq('49FD46E6C4B45C55D4AC')
+ expect(ds.flags).to eq(0)
+ expect(ds.protocol).to eq(3)
+ expect(ds.alg).to eq(5)
+ expect(ds.public_key).to eq('700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f')
+ end
+
end
context 'with juridical persion as an owner' do
@@ -525,7 +613,7 @@ describe 'EPP Domain', epp: true do
end
context 'with valid domain' do
- before(:each) { Fabricate(:domain, name: 'example.ee', registrar: EppUser.first.registrar) }
+ before(:each) { Fabricate(:domain, name: 'example.ee', registrar: EppUser.first.registrar, dnskeys: []) }
it 'renews a domain' do
exp_date = (Date.today + 1.year)
@@ -566,8 +654,28 @@ describe 'EPP Domain', epp: true do
d.domain_statuses.build(value: DomainStatus::CLIENT_HOLD, description: 'Payment overdue.')
d.nameservers.build(hostname: 'ns1.example.com', ipv4: '192.168.1.1', ipv6: '1080:0:0:0:8:800:200C:417A')
- d.dnskeys.build(flags: 257, protocol: 3, alg: 3, public_key: 'AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8')
- d.dnskeys.build(flags: 0, protocol: 3, alg: 5, public_key: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f')
+ d.dnskeys.build(
+ ds_key_tag: '123',
+ ds_alg: 3,
+ ds_digest_type: 1,
+ ds_digest: 'abc',
+ flags: 257,
+ protocol: 3,
+ alg: 3,
+ public_key: 'AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8'
+ )
+
+ d.dnskeys.build(
+ ds_key_tag: '123',
+ ds_alg: 3,
+ ds_digest_type: 1,
+ ds_digest: 'abc',
+ flags: 0,
+ protocol: 3,
+ alg: 5,
+ public_key: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f'
+ )
+
d.save
response = epp_request(domain_info_xml, :xml)
@@ -580,12 +688,12 @@ describe 'EPP Domain', epp: true do
expect(inf_data.css('status').first[:s]).to eq('clientHold')
expect(inf_data.css('registrant').text).to eq(d.owner_contact_code)
- admin_contacts_from_request = inf_data.css('contact[type="admin"]').map { |x| x.text }
+ admin_contacts_from_request = inf_data.css('contact[type="admin"]').map(&:text)
admin_contacts_existing = d.admin_contacts.pluck(:code)
expect(admin_contacts_from_request).to eq(admin_contacts_existing)
- hosts_from_request = inf_data.css('hostObj').map { |x| x.text }
+ hosts_from_request = inf_data.css('hostObj').map(&:text)
hosts_existing = d.nameservers.where(ipv4: nil).pluck(:hostname)
expect(hosts_from_request).to eq(hosts_existing)
@@ -597,13 +705,22 @@ describe 'EPP Domain', epp: true do
expect(inf_data.css('exDate').text).to eq(d.valid_to.to_time.utc.to_s)
expect(inf_data.css('pw').text).to eq(d.auth_info)
- dnskey_1 = inf_data.css('dnskey')[0]
+ ds_data_1 = response[:parsed].css('dsData')[0]
+
+ expect(ds_data_1.css('keyTag').first.text).to eq('123')
+ expect(ds_data_1.css('alg').first.text).to eq('3')
+ expect(ds_data_1.css('digestType').first.text).to eq('1')
+ expect(ds_data_1.css('digest').first.text).to eq('abc')
+
+ dnskey_1 = ds_data_1.css('keyData')[0]
expect(dnskey_1.css('flags').first.text).to eq('257')
expect(dnskey_1.css('protocol').first.text).to eq('3')
expect(dnskey_1.css('alg').first.text).to eq('3')
expect(dnskey_1.css('pubKey').first.text).to eq('AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8')
- dnskey_2 = inf_data.css('dnskey')[1]
+ ds_data_2 = response[:parsed].css('dsData')[1]
+
+ dnskey_2 = ds_data_2.css('keyData')[0]
expect(dnskey_2.css('flags').first.text).to eq('0')
expect(dnskey_2.css('protocol').first.text).to eq('3')
expect(dnskey_2.css('alg').first.text).to eq('5')
@@ -632,30 +749,30 @@ describe 'EPP Domain', epp: true do
{ hostObj: { value: 'ns2.example.com' } }
]
},
- dnssec: [
- {
- dnskey: {
- flags: { value: '0' },
- protocol: { value: '3' },
- alg: { value: '5' },
- pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
- }
- },
- {
- dnskey: {
- flags: { value: '256' },
- protocol: { value: '3' },
- alg: { value: '254' },
- pubKey: { value: '841936717ae427ace63c28d04918569a841936717ae427ace63c28d0' }
- }
- }
- ],
_other: [
{ contact: { value: 'mak21', attrs: { type: 'tech' } } },
{ status: { value: 'Payment overdue.', attrs: { s: 'clientHold', lang: 'en' } } },
{ status: { value: '', attrs: { s: 'clientUpdateProhibited' } } }
]
]
+ }, {
+ add: [
+ { keyData: {
+ flags: { value: '0' },
+ protocol: { value: '3' },
+ alg: { value: '5' },
+ pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
+ }
+ },
+ {
+ keyData: {
+ flags: { value: '256' },
+ protocol: { value: '3' },
+ alg: { value: '254' },
+ pubKey: { value: '841936717ae427ace63c28d04918569a841936717ae427ace63c28d0' }
+ }
+ }
+ ]
})
response = epp_request(xml, :xml)
@@ -680,11 +797,9 @@ describe 'EPP Domain', epp: true do
expect(d.domain_statuses.first.value).to eq('clientHold')
expect(d.domain_statuses.last.value).to eq('clientUpdateProhibited')
-
expect(d.dnskeys.count).to eq(2)
response = epp_request(xml, :xml)
-
expect(response[:results][0][:result_code]).to eq('2302')
expect(response[:results][0][:msg]).to eq('Nameserver already exists on this domain')
expect(response[:results][0][:value]).to eq('ns1.example.com')
@@ -716,33 +831,35 @@ describe 'EPP Domain', epp: true do
{ hostObj: { value: 'ns2.example.com' } }
]
},
- dnssec: [
- {
- dnskey: {
- flags: { value: '0' },
- protocol: { value: '3' },
- alg: { value: '5' },
- pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
- }
- },
- {
- dnskey: {
- flags: { value: '256' },
- protocol: { value: '3' },
- alg: { value: '254' },
- pubKey: { value: '841936717ae427ace63c28d04918569a841936717ae427ace63c28d0' }
- }
- }
- ],
_other: [
{ contact: { value: 'mak21', attrs: { type: 'tech' } } },
{ status: { value: 'Payment overdue.', attrs: { s: 'clientHold', lang: 'en' } } },
{ status: { value: '', attrs: { s: 'clientUpdateProhibited' } } }
]
]
+ }, {
+ add: [
+ { keyData: {
+ flags: { value: '0' },
+ protocol: { value: '3' },
+ alg: { value: '5' },
+ pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
+ }
+ },
+ {
+ keyData: {
+ flags: { value: '256' },
+ protocol: { value: '3' },
+ alg: { value: '254' },
+ pubKey: { value: '841936717ae427ace63c28d04918569a841936717ae427ace63c28d0' }
+ }
+ }
+ ]
})
epp_request(xml, :xml)
+ d = Domain.last
+ expect(d.dnskeys.count).to eq(2)
xml = domain_update_xml({
rem: [
@@ -751,24 +868,22 @@ describe 'EPP Domain', epp: true do
{ hostObj: { value: 'ns1.example.com' } }
]
},
- dnssec: [
- {
- dnskey: {
- pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
- }
- }
- ],
_other: [
{ contact: { value: 'mak21', attrs: { type: 'tech' } } },
{ status: { value: '', attrs: { s: 'clientHold' } } }
]
]
+ }, {
+ rem: [
+ { keyData: {
+ pubKey: { value: '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' }
+ }
+ }
+ ]
})
- d = Domain.last
- expect(d.dnskeys.count).to eq(2)
+ epp_request(xml, :xml)
- response = epp_request(xml, :xml)
expect(d.dnskeys.count).to eq(1)
expect(d.domain_statuses.count).to eq(1)
diff --git a/spec/epp/epp_helper_spec.rb b/spec/epp/epp_helper_spec.rb
index 79f13ec37..5901f603a 100644
--- a/spec/epp/epp_helper_spec.rb
+++ b/spec/epp/epp_helper_spec.rb
@@ -16,19 +16,21 @@ describe 'EPP Helper', epp: true do
ns2.example.net
jd1234
-
-
- 257
- 3
- 5
- AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8
-
-
sh8013
sh8013
sh801333
+
+
+
+ 257
+ 3
+ 5
+ AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8
+
+
+
ABC-12345
@@ -52,19 +54,21 @@ describe 'EPP Helper', epp: true do
ns2.test.net
32fsdaf
-
-
- 257
- 3
- 5
- AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8
-
-
2323rafaf
3dgxx
345xxv
+
+
+
+ 257
+ 3
+ 5
+ AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8
+
+
+
ABC-12345
@@ -72,16 +76,16 @@ describe 'EPP Helper', epp: true do
xml = domain_create_xml({
name: { value: 'one.ee' },
- period: {value: '345', attrs: { unit: 'd' } },
+ period: { value: '345', attrs: { unit: 'd' } },
ns: [
- { hostObj: {value: 'ns1.test.net' } },
- { hostObj: {value: 'ns2.test.net' } }
+ { hostObj: { value: 'ns1.test.net' } },
+ { hostObj: { value: 'ns2.test.net' } }
],
registrant: { value: '32fsdaf' },
_other: [
- { contact: {value: '2323rafaf', attrs: { type: 'admin' } } },
- { contact: {value: '3dgxx', attrs: { type: 'tech' } } },
- { contact: {value: '345xxv', attrs: { type: 'tech' } } }
+ { contact: { value: '2323rafaf', attrs: { type: 'admin' } } },
+ { contact: { value: '3dgxx', attrs: { type: 'tech' } } },
+ { contact: { value: '345xxv', attrs: { type: 'tech' } } }
]
})
@@ -109,9 +113,8 @@ describe 'EPP Helper', epp: true do
period: nil,
ns: nil,
registrant: nil,
- _other: nil,
- dnssec: nil
- })
+ _other: nil
+ }, false)
generated = Nokogiri::XML(xml).to_s.squish
expect(generated).to eq(expected)
@@ -452,7 +455,6 @@ describe 'EPP Helper', epp: true do
generated = Nokogiri::XML(domain_delete_xml).to_s.squish
expect(generated).to eq(expected)
-
expected = Nokogiri::XML('
diff --git a/spec/fabricators/dnskey_fabricator.rb b/spec/fabricators/dnskey_fabricator.rb
new file mode 100644
index 000000000..fb1fb5c67
--- /dev/null
+++ b/spec/fabricators/dnskey_fabricator.rb
@@ -0,0 +1,7 @@
+Fabricator(:dnskey) do
+ alg 8
+ flags 257
+ protocol 3
+ public_key 'AwEAAaOf5+lz3ftsL+0CCvfJbhUF/NVsNh8BKo61oYs5fXVbuWDiH872 LC8uKDO92TJy7Q4TF9XMAKMMlf1GMAxlRspD749SOCTN00sqfWx1OMTu a28L1PerwHq7665oDJDKqR71btcGqyLKhe2QDvCdA0mENimF1NudX1BJ DDFi6oOZ0xE/0CuveB64I3ree7nCrwLwNs56kXC4LYoX3XdkOMKiJLL/ MAhcxXa60CdZLoRtTEW3z8/oBq4hEAYMCNclpbd6y/exScwBxFTdUfFk KsdNcmvai1lyk9vna0WQrtpYpHKMXvY9LFHaJxCOLR4umfeQ42RuTd82 lqfU6ClMeXs='
+ ds_digest_type 2
+end
diff --git a/spec/fabricators/domain_fabricator.rb b/spec/fabricators/domain_fabricator.rb
index 7f42c9258..d1063a096 100644
--- a/spec/fabricators/domain_fabricator.rb
+++ b/spec/fabricators/domain_fabricator.rb
@@ -8,4 +8,5 @@ Fabricator(:domain) do
admin_contacts(count: 1) { Fabricate(:contact) }
registrar
auth_info '98oiewslkfkd'
+ dnskeys(count: 1)
end
diff --git a/spec/fabricators/setting_group_fabricator.rb b/spec/fabricators/setting_group_fabricator.rb
index 8906fe0d2..13129a6bf 100644
--- a/spec/fabricators/setting_group_fabricator.rb
+++ b/spec/fabricators/setting_group_fabricator.rb
@@ -38,3 +38,15 @@ Fabricator(:domain_general_setting_group, from: :setting_group) do
]
end
end
+
+Fabricator(:dnskeys_setting_group, from: :setting_group) do
+ code 'dnskeys'
+ settings do
+ [
+ Fabricate(:setting, code: Setting::DS_ALGORITHM, value: 2),
+ Fabricate(:setting, code: Setting::ALLOW_DS_DATA, value: 1),
+ Fabricate(:setting, code: Setting::ALLOW_DS_DATA_WITH_KEYS, value: 1),
+ Fabricate(:setting, code: Setting::ALLOW_KEY_DATA, value: 1)
+ ]
+ end
+end
diff --git a/spec/features/client_contact_spec.rb b/spec/features/client_contact_spec.rb
index 3f56dccd1..81b5971dd 100644
--- a/spec/features/client_contact_spec.rb
+++ b/spec/features/client_contact_spec.rb
@@ -1,8 +1,8 @@
require 'rails_helper'
feature 'Contact management', type: :feature do
- #background do
- #end
+ # background do
+ # end
before(:each) do
Fabricate(:user, country: Fabricate(:country, iso: 'EE'), admin: false, username: 'zone')
diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb
index f63e2455a..44a6d23a0 100644
--- a/spec/models/contact_spec.rb
+++ b/spec/models/contact_spec.rb
@@ -51,6 +51,7 @@ describe Contact, '#relations_with_domain?' do
context 'with relation' do
before(:each) do
Fabricate(:domain_validation_setting_group)
+ Fabricate(:dnskeys_setting_group)
Fabricate(:domain)
end
@@ -74,7 +75,9 @@ end
describe Contact, '#up_id' do
before(:each) do
- #Fabricate(:contact, code: 'asd12', created_by: Fabricate(:epp_user), updated_by: Fabricate(:epp_user), registrar: zone)
+ # Fabricate(:contact, code: 'asd12',
+ # created_by: Fabricate(:epp_user),
+ # updated_by: Fabricate(:epp_user), registrar: zone)
@epp_user = Fabricate(:epp_user)
@contact = Fabricate.build(:contact, code: 'asd12', created_by: @epp_user, updated_by: @epp_user)
end
diff --git a/spec/models/dnskey_spec.rb b/spec/models/dnskey_spec.rb
new file mode 100644
index 000000000..6663f148a
--- /dev/null
+++ b/spec/models/dnskey_spec.rb
@@ -0,0 +1,18 @@
+require 'rails_helper'
+
+describe Dnskey do
+ before(:each) do
+ Fabricate(:domain_validation_setting_group)
+ Fabricate(:dnskeys_setting_group)
+ end
+
+ it { should belong_to(:domain) }
+
+ it 'generates digest' do
+ d = Fabricate(:domain, name: 'ria.ee')
+ ds = d.dnskeys.first
+
+ ds.generate_digest
+ expect(ds.ds_digest).to eq('0B62D1BC64EFD1EE652FB102BDF1011BF514CCD9A1A0CFB7472AEA3B01F38C92')
+ end
+end
diff --git a/spec/models/domain_spec.rb b/spec/models/domain_spec.rb
index 9686b5208..1d5dc70c2 100644
--- a/spec/models/domain_spec.rb
+++ b/spec/models/domain_spec.rb
@@ -7,9 +7,13 @@ describe Domain do
it { should have_many(:tech_contacts) }
it { should have_many(:admin_contacts) }
it { should have_many(:domain_transfers) }
+ it { should have_many(:dnskeys) }
context 'with sufficient settings' do
- before(:each) { Fabricate(:domain_validation_setting_group) }
+ before(:each) do
+ Fabricate(:domain_validation_setting_group)
+ Fabricate(:dnskeys_setting_group)
+ end
it 'validates domain name' do
d = Fabricate(:domain)
diff --git a/spec/support/epp.rb b/spec/support/epp.rb
index ac23f8edd..0e86ee795 100644
--- a/spec/support/epp.rb
+++ b/spec/support/epp.rb
@@ -52,7 +52,7 @@ module Epp
### REQUEST TEMPLATES ###
- def domain_create_xml(xml_params = {})
+ def domain_create_xml(xml_params = {}, dnssec_params = {})
defaults = {
name: { value: 'example.ee' },
@@ -62,16 +62,6 @@ module Epp
{ hostObj: { value: 'ns2.example.net' } }
],
registrant: { value: 'jd1234' },
- dnssec: [
- {
- dnskey: {
- flags: { value: '257' },
- protocol: { value: '3' },
- alg: { value: '5' },
- pubKey: { value: 'AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8' }
- }
- }
- ],
_other: [
{ contact: { value: 'sh8013', attrs: { type: 'admin' } } },
{ contact: { value: 'sh8013', attrs: { type: 'tech' } } },
@@ -81,6 +71,19 @@ module Epp
xml_params = defaults.deep_merge(xml_params)
+ dsnsec_defaults = {
+ _other: [
+ { keyData: {
+ flags: { value: '257' },
+ protocol: { value: '3' },
+ alg: { value: '5' },
+ pubKey: { value: 'AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8' }
+ }
+ }]
+ }
+
+ dnssec_params = dsnsec_defaults.deep_merge(dnssec_params) if dnssec_params != false
+
xml = Builder::XmlMarkup.new
xml.instruct!(:xml, standalone: 'no')
@@ -91,6 +94,11 @@ module Epp
generate_xml_from_hash(xml_params, xml, 'domain')
end
end
+ xml.extension do
+ xml.tag!('secDNS:create', 'xmlns:secDNS' => 'urn:ietf:params:xml:ns:secDNS-1.1') do
+ generate_xml_from_hash(dnssec_params, xml, 'secDNS')
+ end
+ end if dnssec_params != false
xml.clTRID 'ABC-12345'
end
end
@@ -161,7 +169,7 @@ module Epp
end
end
- def domain_update_xml(xml_params = {})
+ def domain_update_xml(xml_params = {}, dnssec_params = false)
defaults = {
name: { value: 'example.ee' }
}
@@ -178,6 +186,12 @@ module Epp
generate_xml_from_hash(xml_params, xml, 'domain')
end
end
+
+ xml.extension do
+ xml.tag!('secDNS:create', 'xmlns:secDNS' => 'urn:ietf:params:xml:ns:secDNS-1.1') do
+ generate_xml_from_hash(dnssec_params, xml, 'secDNS')
+ end
+ end if dnssec_params != false
xml.clTRID 'ABC-12345'
end
end