diff --git a/.gitignore b/.gitignore
index 7f705cb07..175f485fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,10 +10,11 @@ capybara-*.html
/spec/tmp
**.orig
config/initializers/secret_token.rb
-config/application.yml
config/secrets.yml
config/database.yml
/export
+/ca
+todo
## Environment normalisation:
/.bundle
@@ -24,3 +25,6 @@ config/database.yml
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
+
+# Ignore application configuration
+/config/application.yml
diff --git a/.rubocop.yml b/.rubocop.yml
index c58f51bdb..ed6970b34 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -77,3 +77,7 @@ Style/AsciiComments:
# because NerdCommenter honors commented code intentions
Style/CommentIndentation:
Enabled: false
+
+# It did not alayws suggested good format
+Style/AlignParameters:
+ Enabled: false
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000..5fc709227
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,27 @@
+language: ruby
+rvm:
+ - 2.2
+ - ruby-head
+env:
+ - DB=postgresql
+sudo: false
+before_install:
+ - gem install bundler
+ - "rm ${BUNDLE_GEMFILE}.lock"
+before_script:
+ - psql -c 'create database registry_test;' -U postgres
+ - psql -c 'create database registry_whois_test;' -U postgres
+ - psql -c 'create database registry_api_log_test;' -U postgres
+ - bundle update
+ - cp config/application-example.yml config/application.yml
+ - cp config/secrets-example.yml config/secrets.yml
+ - cp config/database-travis.yml config/database.yml
+ - RAILS_ENV=test bundle exec rake db:all:schema:load
+ - RAILS_ENV=test bundle exec rake db:seed
+script:
+ - RAILS_ENV=test bundle exec rake
+cache: bundler
+services:
+ - postgresql
+addons:
+ postgresql: "9.3"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 79f0cc390..cc0bd3e74 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,93 +1,11 @@
-12.02.2015
-
-Go to registry shared folder and setup CA directory tree:
-```
-mkdir ca
-cd ca
-mkdir certs crl newcerts private
-chmod 700 private
-touch index.txt
-echo 1000 > serial
-```
+27.02.2015
-Generate the root key (prompts for pass phrase):
-```
-openssl genrsa -aes256 -out private/ca.key.pem 4096
-```
+* Simplified config/application-example.yml,
+ now system will check if all required settings are present in application.yml
-Configure OpenSSL:
-```
-sudo su -
-cd /etc/ssl/
-cp openssl.cnf openssl.cnf.bak
-nano openssl.cnf
-exit
-```
+19.02.2015
-Make sure the following options are in place:
-```
-[ CA_default ]
-# Where everything is kept
-dir = /home/registry/registry/shared/ca
-
-[ usr_cert ]
-# These extensions are added when 'ca' signs a request.
-basicConstraints=CA:FALSE
-keyUsage = nonRepudiation, digitalSignature, keyEncipherment
-nsComment = "OpenSSL Generated Certificate"
-subjectKeyIdentifier=hash
-authorityKeyIdentifier=keyid,issuer
-
-[ v3_ca ]
-# Extensions for a typical CA
-subjectKeyIdentifier=hash
-authorityKeyIdentifier=keyid:always,issuer
-basicConstraints = CA:true
-keyUsage = cRLSign, keyCertSign
-
-[ policy_match ]
-countryName = optional
-stateOrProvinceName = optional
-organizationName = optional
-organizationalUnitName = optional
-commonName = optional
-emailAddress = optional
-```
-
-Issue the root certificate (prompts for additional data):
-```
-openssl req -new -x509 -days 3650 -key private/ca.key.pem -sha256 -extensions v3_ca -out certs/ca.cert.pem
-chmod 444 certs/ca.cert.pem
-```
-
-Configure EPP virtual host:
-```
-sudo nano /etc/apache2/sites-enabled/epp.conf
-```
-
-Replace this line:
-```
-SSLVerifyClient optional_no_ca
-```
-
-With these lines:
-```
- SSLVerifyClient require
- SSLVerifyDepth 1
- SSLCACertificateFile /home/registry/registry/shared/ca/certs/ca.cert.pem
-```
-
-Reload apache:
-```
-sudo /etc/init.d/apache2 reload
-```
-
-Configure application.yml to match the CA settings:
-```
-ca_cert_path: '/home/registry/registry/shared/ca/certs/ca.cert.pem'
-ca_key_path: '/home/registry/registry/shared/ca/private/ca.key.pem'
-ca_key_password: 'registryalpha'
-```
+* Cetrificate only enabled, please setup certificates following doc/certificate.md document.
20.01.2015
diff --git a/Gemfile b/Gemfile
index c901c0e56..e0bf28b53 100644
--- a/Gemfile
+++ b/Gemfile
@@ -5,10 +5,16 @@ gem 'rails', '4.2.0'
gem 'iso8601', '~> 0.8.2' # for dates and times
gem 'hashie_rails', '~> 0.0.1'
+# load env
+gem 'figaro', '~> 1.1.0'
+
# model related
gem 'pg', '~> 0.18.0'
gem 'ransack', '~> 1.5.1' # for searching
-gem 'paper_trail', '~> 4.0.0.beta2' # archiving
+# with polymorphic fix
+gem 'paper_trail',
+ github: 'airblade/paper_trail',
+ ref: 'a453811226ec4ea59753ba6b827e390ced2fc140' # '~> 4.0.0.beta2' # archiving
gem 'rails-settings-cached', '~> 0.4.1' # for settings
gem 'delayed_job_active_record', '~> 4.0.3' # delayed job
@@ -110,4 +116,7 @@ group :development, :test do
# dev tools
gem 'unicorn'
+
+ # for travis
+ gem 'rake'
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 9097efcef..478d7604a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,3 +1,13 @@
+GIT
+ remote: git://github.com/airblade/paper_trail.git
+ revision: a453811226ec4ea59753ba6b827e390ced2fc140
+ ref: a453811226ec4ea59753ba6b827e390ced2fc140
+ specs:
+ paper_trail (4.0.0.beta3)
+ activerecord (>= 3.0, < 6.0)
+ activesupport (>= 3.0, < 6.0)
+ request_store (~> 1.1.0)
+
GIT
remote: git://github.com/haml/html2haml.git
revision: 6984f50bdbbd6291535027726a5697f28778ee8d
@@ -142,6 +152,8 @@ GEM
i18n (~> 0.5)
fastercsv (1.5.5)
ffi (1.9.6)
+ figaro (1.1.0)
+ thor (~> 0.14)
flay (2.4.0)
ruby_parser (~> 3.0)
sexp_processor (~> 4.0)
@@ -235,9 +247,6 @@ GEM
nprogress-rails (0.1.6.5)
open4 (1.3.4)
orm_adapter (0.5.0)
- paper_trail (4.0.0.beta2)
- activerecord (>= 3.0, < 6.0)
- activesupport (>= 3.0, < 6.0)
parser (2.2.0.2)
ast (>= 1.1, < 3.0)
pg (0.18.1)
@@ -309,6 +318,7 @@ GEM
ruby_parser (~> 3.3)
sexp_processor
ref (1.0.5)
+ request_store (1.1.0)
responders (2.0.2)
railties (>= 4.2.0.alpha, < 5)
rspec (3.0.0)
@@ -451,6 +461,7 @@ DEPENDENCIES
epp-xml (~> 0.10.4)
fabrication (~> 2.12.2)
faker (~> 1.3.0)
+ figaro (~> 1.1.0)
grape (~> 0.10.1)
guard (~> 2.6.1)
guard-rails (~> 0.7.0)
@@ -469,7 +480,7 @@ DEPENDENCIES
newrelic_rpm (~> 3.9.9.275)
nokogiri (~> 1.6.2.1)
nprogress-rails (~> 0.1.6.5)
- paper_trail (~> 4.0.0.beta2)
+ paper_trail!
pg (~> 0.18.0)
phantomjs (~> 1.9.7.1)
phantomjs-binaries (~> 1.9.2.4)
@@ -478,6 +489,7 @@ DEPENDENCIES
railroady (~> 1.3.0)
rails (= 4.2.0)
rails-settings-cached (~> 0.4.1)
+ rake
ransack (~> 1.5.1)
rspec-rails (~> 3.0.2)
rubocop (~> 0.26.1)
diff --git a/Guardfile b/Guardfile
index eab74ee21..e6d0a443a 100644
--- a/Guardfile
+++ b/Guardfile
@@ -3,11 +3,11 @@ group :red_green_refactor, halt_on_fail: true do
# be sure you have apache2 configured to
# accept EPP request on port 701, what proxy to 8989.
# port and environment is just for correct notification, all is overwritten by CLI
- guard :rails, port: 8989, environment: 'test' do
- # guard :rails, port: 8989, environment: 'test', CLI: 'RAILS_ENV=test unicorn -p 8989' do
- watch('Gemfile.lock')
- watch(%r{^(config|lib)/.*})
- end
+ # guard :rails, port: 8989, environment: 'test' do
+ # # guard :rails, port: 8989, environment: 'test', CLI: 'RAILS_ENV=test unicorn -p 8989' do
+ # watch('Gemfile.lock')
+ # watch(%r{^(config|lib)/.*})
+ # end
guard :rspec, cmd: 'spring rspec', notification: false do
watch(%r{^spec/.+_spec\.rb$})
@@ -18,6 +18,8 @@ group :red_green_refactor, halt_on_fail: true do
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
+ watch(%r{^app/controllers/epp/(.+)_(controller)\.rb$}) { |m| ["spec/epp/#{m[1].sub(/s$/,'')}_spec.rb"] }
+ watch(%r{^app/models/epp/(.+)\.rb$}) { |m| "spec/epp/#{m[1]}_spec.rb" }
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
watch('config/routes.rb') { "spec/routing" }
watch('app/controllers/application_controller.rb') { "spec/controllers" }
diff --git a/README.md b/README.md
index 92b8f67c6..0380f6a75 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ Installation
### Registry app
-Usual Rails 4 app installation (rbenv install is under Debian build doc)
+Registry based on Rails 4 installation (rbenv install is under Debian build doc)
Manual demo install and database setup:
@@ -32,44 +32,11 @@ Manual demo install and database setup:
cd demo-registry
rbenv local 2.2.0
bundle
+ cp config/application-example.yml config/application.yml # and edit it
cp config/database-example.yml config/database.yml # and edit it
- cp config/initializers/devise_secret_example.rb.txt config/initializers/devise_secret.rb # and edit
+ bundle exec rake db:all:setup # for production, please follow deployment howto
bundle exec rake assets:precompile
-Create registry database manually, example:
-
- create database registry_production owner registry encoding 'UTF-8' LC_COLLATE 'et_EE.utf8' LC_CTYPE 'et_EE.utf8' template template0;
- rake db:schema:load
- rake db:seeds
-
-Or create all databases:
-
- rake db:all:setup # will create all databases and loads all schemas
- rake db:all:create # creates all databases
- rake db:all:schema:load # loads all schemas
- rake db:all:schema:dump # dumps all schemas
-
-Production install (database schema should be loaded and seeds should be present)
-
- # at your local machine
- git clone git@github.com:internetee/registry.git
- cd registry
- rbenv local 2.2.0 # more info about rbenv at debian doc
- gem install mina
- mina pr setup # one time, only creates missing directories
- ssh registry
-
- # at your server
- cd registry
- cp current/config/application-example.yml shared/config/application.yml # and edit it
- cp current/config/database-example.yml shared/config/database.yml # and edit it
-
- vi /etc/apache2/sites-enabled/registry.conf # add conf and all needed serts
- vi /etc/apache2/sites-enabled/epp.conf # add epp conf, restart apache
- exit
- # at your local machine
- mina pr deploy # this is command you use in every application code update
-
### Apache with patched mod_epp (Debian 7/Ubuntu 14.04 LTS)
sudo apt-get install apache2
@@ -152,7 +119,12 @@ Be sure to update paths to match your system configuration.
SSLVerifyClient require
SSLVerifyDepth 1
- SSLCACertificateFile /home/registry/registry/shared/ca/certs/ca.cert.pem
+ SSLCACertificateFile /home/registry/registry/shared/ca/certs/ca.crt.pem
+ SSLCARevocationFile /home/registry/registry/shared/ca/crl/crl.pem
+ # Uncomment this when upgrading to apache 2.4:
+ # SSLCARevocationCheck chain
+
+ RequestHeader set SSL_CLIENT_S_DN_CN "%{SSL_CLIENT_S_DN_CN}s"
EPPEngine On
EPPCommandRoot /proxy/command
@@ -182,6 +154,21 @@ All registry demo data can be found at:
Initially you can use two type of users: admin users and EPP users.
+### Certificates setup
+
+* [Certificates setup](/doc/certificates.md)
+
+
+### Deployment
+
+* [Application build and update](/doc/application_build_doc.md)
+
+
+### Autotesting
+
+* [Testing](/doc/testing.md)
+
+
### EPP web client
Please follow EPP web client readme:
@@ -196,85 +183,7 @@ Please follow WHOIS server readme:
https://github.com/internetee/whois
-Deployment
-----------
+## Code Status
-* [Debian build](/doc/debian_build_doc.md)
-* [Application build and update](/doc/application_build_doc.md)
-
-CRON
-----
-
-Crontab can be setup after deploy. Jobs can be viewed [here](/config/schedule.rb).
-
- mina pr cron:setup # to update the crontab.
- mina pr cron:clear # to clear crontab.
-
-Autotesting
------------
-
-* Before running tests for the first time: `RAILS_ENV=test rake db:seed`
-* Run tests: `rake`
-* Run EPP tests: `rake test:epp`
-* Run all but EPP tests: `rake test:other`
-
-To see internal errors while testing EPP
-
- unicorn -E test -p 8989
- rake spec:epp
-
-### Apache mod_epp autotesting/debugging
-
-Autotesting Apache mod_epp without Registry app.
-
- sudo apt-get install apache2-dbg
-
-Includes htpasswd command to generate authentication files
-
- sudo apt-get install apache2-utils
-
-For manual debugging purposes, standalone CGI scripts can be used:
-This needs a static greeting file, so you will have to make /var/www writable.
-
-```apache
-
-
- Options ExecCGI
- SetHandler cgi-script
-
-
- Listen 1700
-
-
- EPPEngine On
- EPPCommandRoot /cgi-bin/epp/command
- EPPSessionRoot /cgi-bin/epp/session
- EPPErrorRoot /cgi-bin/epp/error
-
- Alias /cgi-bin/epp/session/hello /var/www/html/epp/session-hello
-
- Alias /cgi-bin/epp/session/login /usr/lib/cgi-bin/epp/session-login
- Alias /cgi-bin/epp/session/logout /usr/lib/cgi-bin/epp/session-logout
- Alias /cgi-bin/epp/error/schema /usr/lib/cgi-bin/epp/error-schema
- Alias /cgi-bin/epp/command/create /usr/lib/cgi-bin/epp/create
- Alias /cgi-bin/epp/command/info /usr/lib/cgi-bin/epp/info
-
- EPPAuthURI /epp/auth/login
-
- AuthType Basic
- AuthName "EPP"
- AuthUserFile /etc/apache2/htpasswd
- require valid-user
-
-
-
-```
-
- sudo a2enmod cgi
- sudo a2enmod authn_file # will be used for non implicit authentication URIs
- sudo htpasswd -c /etc/apache2/htpasswd test
- Type "test" when prompted
- cd /usr/lib/cgi-bin
- mkdir epp
-
-Copy the files from $mod_epp/examples/cgis to /usr/lib/cgi-bin/epp
+Alpha release status, only model tests:
+[](https://travis-ci.org/domify/registry)
diff --git a/app/controllers/admin/api_users_controller.rb b/app/controllers/admin/api_users_controller.rb
index 54105e87e..27bed6a80 100644
--- a/app/controllers/admin/api_users_controller.rb
+++ b/app/controllers/admin/api_users_controller.rb
@@ -12,10 +12,7 @@ class Admin::ApiUsersController < AdminController
end
def create
- app = api_user_params
- app[:csr] = params[:api_user][:csr].open.read if params[:api_user][:csr]
-
- @api_user = ApiUser.new(app)
+ @api_user = ApiUser.new(api_user_params)
if @api_user.save
flash[:notice] = I18n.t('record_created')
@@ -31,10 +28,7 @@ class Admin::ApiUsersController < AdminController
def edit; end
def update
- app = api_user_params
- app[:csr] = params[:api_user][:csr].open.read if params[:api_user][:csr]
-
- if @api_user.update(app)
+ if @api_user.update(api_user_params)
flash[:notice] = I18n.t('record_updated')
redirect_to [:admin, @api_user]
else
@@ -53,14 +47,6 @@ class Admin::ApiUsersController < AdminController
end
end
- def download_csr
- send_data @api_user.csr, filename: "#{@api_user.username}.csr.pem"
- end
-
- def download_crt
- send_data @api_user.crt, filename: "#{@api_user.username}.crt.pem"
- end
-
private
def set_api_user
@@ -68,6 +54,6 @@ class Admin::ApiUsersController < AdminController
end
def api_user_params
- params.require(:api_user).permit(:username, :password, :csr, :active, :registrar_id, :registrar_typeahead)
+ params.require(:api_user).permit(:username, :password, :active, :registrar_id, :registrar_typeahead)
end
end
diff --git a/app/controllers/admin/certificates_controller.rb b/app/controllers/admin/certificates_controller.rb
new file mode 100644
index 000000000..4bc05fec4
--- /dev/null
+++ b/app/controllers/admin/certificates_controller.rb
@@ -0,0 +1,68 @@
+class Admin::CertificatesController < AdminController
+ load_and_authorize_resource
+ before_action :set_certificate, :set_api_user, only: [:sign, :show, :download_csr, :download_crt, :revoke]
+
+ def show
+ @csr = OpenSSL::X509::Request.new(@certificate.csr) if @certificate.csr
+ @crt = OpenSSL::X509::Certificate.new(@certificate.crt) if @certificate.crt
+ end
+
+ def new
+ set_api_user
+ @certificate = Certificate.new
+ end
+
+ def create
+ @api_user = ApiUser.find(params[:api_user_id])
+ csr = certificate_params[:csr].open.read if certificate_params[:csr]
+
+ @certificate = @api_user.certificates.build(csr: csr)
+ if @api_user.save
+ flash[:notice] = I18n.t('record_created')
+ redirect_to [:admin, @api_user, @certificate]
+ else
+ flash.now[:alert] = I18n.t('failed_to_create_record')
+ render 'new'
+ end
+ end
+
+ def sign
+ if @certificate.sign!
+ flash[:notice] = I18n.t('record_updated')
+ else
+ flash[:alert] = I18n.t('failed_to_update_record')
+ end
+ redirect_to [:admin, @api_user, @certificate]
+ end
+
+ def revoke
+ if @certificate.revoke!
+ flash[:notice] = I18n.t('record_updated')
+ else
+ flash[:alert] = I18n.t('failed_to_update_record')
+ end
+ redirect_to [:admin, @api_user, @certificate]
+ end
+
+ def download_csr
+ send_data @certificate.csr, filename: "#{@api_user.username}.csr.pem"
+ end
+
+ def download_crt
+ send_data @certificate.crt, filename: "#{@api_user.username}.crt.pem"
+ end
+
+ private
+
+ def set_certificate
+ @certificate = Certificate.find(params[:id])
+ end
+
+ def set_api_user
+ @api_user = ApiUser.find(params[:api_user_id])
+ end
+
+ def certificate_params
+ params.require(:certificate).permit(:csr)
+ end
+end
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
index 9810f7bdf..8bea17fdf 100644
--- a/app/controllers/admin_controller.rb
+++ b/app/controllers/admin_controller.rb
@@ -1,4 +1,3 @@
class AdminController < ApplicationController
before_action :authenticate_user!
- check_authorization
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 81acf1313..8840e4989 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,4 +1,6 @@
class ApplicationController < ActionController::Base
+ check_authorization unless: :devise_controller?
+
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
@@ -9,8 +11,14 @@ class ApplicationController < ActionController::Base
params[resource] &&= send(method) if respond_to?(method, true)
end
+ rescue_from CanCan::AccessDenied do |exception|
+ redirect_to admin_dashboard_path, alert: exception.message
+ end
+
def after_sign_in_path_for(_resource)
- return session[:user_return_to].to_s if session[:user_return_to] && session[:user_return_to] != login_path
+ if session[:user_return_to] && session[:user_return_to] != login_path
+ return session[:user_return_to].to_s
+ end
admin_dashboard_path
end
@@ -34,9 +42,3 @@ class ApplicationController < ActionController::Base
end
end
end
-
-class ApplicationController < ActionController::Base
- rescue_from CanCan::AccessDenied do |exception|
- redirect_to admin_dashboard_path, alert: exception.message
- end
-end
diff --git a/app/controllers/epp/contacts_controller.rb b/app/controllers/epp/contacts_controller.rb
index 6aa5efce3..d93916055 100644
--- a/app/controllers/epp/contacts_controller.rb
+++ b/app/controllers/epp/contacts_controller.rb
@@ -1,188 +1,125 @@
class Epp::ContactsController < EppController
- helper WhodunnitHelper ## Refactor this?
-
- def create
- @contact = Contact.new(contact_and_address_attributes)
- @contact.registrar = current_user.registrar
- render_epp_response '/epp/contacts/create' and return if @contact.save
- handle_errors(@contact)
- end
-
- def update
- # FIXME: Update returns 2303 update multiple times
- code = params_hash['epp']['command']['update']['update'][:id]
-
- @contact = Contact.where(code: code).first
- # if update_rights? && @contact.update_attributes(contact_and_address_attributes(:update))
- if owner? && @contact.update_attributes(contact_and_address_attributes(:update))
- render_epp_response 'epp/contacts/update'
- else
- contact_exists?(code)
- handle_errors(@contact) and return
- end
- end
-
- # rubocop:disable Metrics/CyclomaticComplexity
- def delete
- @contact = find_contact
- handle_errors(@contact) and return unless rights? # owner?
- handle_errors(@contact) and return unless @contact
- handle_errors(@contact) and return unless @contact.destroy_and_clean
-
- render_epp_response '/epp/contacts/delete'
- end
- # rubocop:enable Metrics/CyclomaticComplexity
-
- def check
- ph = params_hash['epp']['command']['check']['check']
- @contacts = Contact.check_availability(ph[:id])
- render_epp_response '/epp/contacts/check'
- end
+ before_action :find_contact, only: [:info, :update, :delete]
+ before_action :find_password, only: [:info, :update, :delete]
def info
- handle_errors(@contact) and return unless @contact && rights?
- # handle_errors(@contact) and return unless rights?
- @disclosure = ContactDisclosure.default_values.merge(@contact.disclosure.try(:as_hash) || {})
- @disclosure_policy = @contact.disclosure.try(:attributes_with_flag)
- @owner = owner?(false)
- # need to reload contact eagerly
- @contact = find_contact if @owner # for clarity, could just be true
+ authorize! :info, @contact, @password
render_epp_response 'epp/contacts/info'
end
+ def check
+ authorize! :check, Epp::Contact
+
+ ids = params[:parsed_frame].css('id').map(&:text)
+ @results = Contact.check_availability(ids)
+ render_epp_response '/epp/contacts/check'
+ end
+
+ def create
+ authorize! :create, Epp::Contact
+ @contact = Epp::Contact.new(params[:parsed_frame], current_user.registrar)
+
+ if @contact.save
+ render_epp_response '/epp/contacts/create'
+ else
+ handle_errors(@contact)
+ end
+ end
+
+ def update
+ authorize! :update, @contact, @password
+
+ if @contact.update_attributes(params[:parsed_frame])
+ render_epp_response 'epp/contacts/update'
+ else
+ handle_errors(@contact)
+ end
+ end
+
+ def delete
+ authorize! :delete, @contact, @password
+
+ if @contact.destroy_and_clean
+ render_epp_response '/epp/contacts/delete'
+ else
+ handle_errors(@contact)
+ end
+ end
+
def renew
+ authorize! :renew, Epp::Contact
epp_errors << { code: '2101', msg: t(:'errors.messages.unimplemented_command') }
handle_errors
end
- ## HELPER METHODS
-
private
- ## CREATE
- def validate_create
- @ph = params_hash['epp']['command']['create']['create']
- return false unless validate_params
- xml_attrs_present?(@ph, [%w(postalInfo name), %w(postalInfo addr city), %w(postalInfo addr cc),
- %w(ident), %w(voice), %w(email)])
-
- epp_errors.empty?
+ def find_password
+ @password = params[:parsed_frame].css('authInfo pw').text
end
- ## UPDATE
- def validate_updatezz
- @ph = params_hash['epp']['command']['update']['update']
- update_attrs_present?
- # xml_attrs_present?(@ph, [['id'], %w(authInfo pw)])
- xml_attrs_present?(@ph, [['id']])
- end
-
- def contact_exists?(code)
- return true if @contact.is_a?(Contact)
- epp_errors << { code: '2303', msg: t('errors.messages.epp_obj_does_not_exist'),
- value: { obj: 'id', val: code } }
- end
-
- def update_attrs_present?
- return true if params[:parsed_frame].css('add').present?
- return true if params[:parsed_frame].css('rem').present?
- return true if params[:parsed_frame].css('chg').present?
- epp_errors << { code: '2003', msg: I18n.t('errors.messages.required_parameter_missing', key: 'add, rem or chg') }
- end
-
- ## DELETE
- def validate_delete
- @ph = params_hash['epp']['command']['delete']['delete']
- xml_attrs_present?(@ph, [['id']])
- end
-
- ## check
- def validate_check
- @ph = params_hash['epp']['command']['check']['check']
- xml_attrs_present?(@ph, [['id']])
- end
-
- ## info
- def validate_info # and process
- @ph = params_hash['epp']['command']['info']['info']
- return false unless xml_attrs_present?(@ph, [['id']])
- @contact = find_contact
- return false unless @contact
- return true if current_user.registrar == @contact.registrar || xml_attrs_present?(@ph, [%w(authInfo pw)])
- false
- end
-
- ## SHARED
-
def find_contact
- contact = Contact.find_by(code: @ph[:id])
- unless contact
- epp_errors << { code: '2303',
- msg: t('errors.messages.epp_obj_does_not_exist'),
- value: { obj: 'id', val: @ph[:id] } }
+ code = params[:parsed_frame].css('id').text.strip.downcase
+ @contact = Epp::Contact.find_by(code: code)
+
+ if @contact.blank?
+ epp_errors << {
+ code: '2303',
+ msg: t('errors.messages.epp_obj_does_not_exist'),
+ value: { obj: 'id', val: code }
+ }
+ fail CanCan::AccessDenied
end
- contact
+ @contact
end
- def owner?(with_errors = true)
- return false unless find_contact
- return true if @contact.registrar == current_user.registrar
- return false unless with_errors
- epp_errors << { code: '2201', msg: t('errors.messages.epp_authorization_error') }
- false
+ #
+ # Validations
+ #
+ def validate_info
+ @prefix = 'info > info >'
+ requires 'id'
end
- def rights?
- pw = @ph.try(:[], :authInfo).try(:[], :pw)
-
- return true if current_user.try(:registrar) == @contact.try(:registrar)
- return true if pw && @contact.auth_info_matches(pw) # @contact.try(:auth_info_matches, pw)
-
- epp_errors << { code: '2200', msg: t('errors.messages.epp_authentication_error') }
- false
+ def validate_check
+ @prefix = 'check > check >'
+ requires 'id'
end
- def update_rights?
- pw = @ph.try(:[], :authInfo).try(:[], :pw)
- return true if pw && @contact.auth_info_matches(pw)
- epp_errors << { code: '2200', msg: t('errors.messages.epp_authentication_error') }
- false
- end
-
- def contact_and_address_attributes(type = :create)
- case type
- when :update
- # TODO: support for rem/add
- contact_hash = merge_attribute_hash(@ph[:chg], type).delete_if { |_k, v| v.empty? }
- else
- contact_hash = merge_attribute_hash(@ph, type)
- end
- contact_hash[:ident_type] = ident_type unless ident_type.nil?
- contact_hash
- end
-
- def merge_attribute_hash(prms, type)
- contact_hash = Contact.extract_attributes(prms, type)
- contact_hash = contact_hash.merge(
- Address.extract_attributes((prms.try(:[], :postalInfo) || []))
+ def validate_create
+ @prefix = 'create > create >'
+ requires(
+ 'postalInfo > name', 'postalInfo > addr > city',
+ 'postalInfo > addr > cc', 'ident', 'voice', 'email'
)
- contact_hash[:disclosure_attributes] =
- ContactDisclosure.extract_attributes(params[:parsed_frame])
-
- contact_hash
+ ident = params[:parsed_frame].css('ident')
+ if ident.present? && ident.text != 'birthday' && ident.attr('cc').blank?
+ epp_errors << {
+ code: '2003',
+ msg: I18n.t('errors.messages.required_attribute_missing', key: 'ident country code missing')
+ }
+ end
+ @prefix = nil
+ requires 'extension > extdata > legalDocument'
end
- def ident_type
- result = params[:parsed_frame].css('ident').first.try(:attributes).try(:[], 'type').try(:value)
- return nil unless result
-
- Contact::IDENT_TYPES.any? { |type| return type if result.include?(type) }
- nil
+ def validate_update
+ @prefix = 'update > update >'
+ if element_count('chg') == 0 && element_count('rem') == 0 && element_count('add') == 0
+ epp_errors << {
+ code: '2003',
+ msg: I18n.t('errors.messages.required_parameter_missing', key: 'add, rem or chg')
+ }
+ end
+ requires 'id', 'authInfo > pw'
+ @prefix = nil
+ requires 'extension > extdata > legalDocument'
end
- def validate_params
- return true if @ph
- epp_errors << { code: '2001', msg: t(:'errors.messages.epp_command_syntax_error') }
- false
+ def validate_delete
+ @prefix = 'delete > delete >'
+ requires 'id', 'authInfo > pw'
+ @prefix = nil
+ requires 'extension > extdata > legalDocument'
end
end
diff --git a/app/controllers/epp/domains_controller.rb b/app/controllers/epp/domains_controller.rb
index 2a4411ba0..97aa0967f 100644
--- a/app/controllers/epp/domains_controller.rb
+++ b/app/controllers/epp/domains_controller.rb
@@ -1,4 +1,6 @@
class Epp::DomainsController < EppController
+ skip_authorization_check # TODO: remove it
+
def create
@domain = Epp::EppDomain.new(domain_create_params)
# @domain.parse_and_attach_domain_dependencies(params[:parsed_frame])
@@ -334,7 +336,7 @@ class Epp::DomainsController < EppController
return domain if domain.auth_info == params[:parsed_frame].css('authInfo pw').text
- if (domain.registrar != current_user.registrar && secure[:secure] == true) &&
+ if (domain.registrar != current_user.registrar) && secure[:secure] == true
epp_errors << {
code: '2302',
msg: I18n.t('errors.messages.domain_exists_but_belongs_to_other_registrar'),
diff --git a/app/controllers/epp/errors_controller.rb b/app/controllers/epp/errors_controller.rb
index 43b8ee6b1..cefa026a0 100644
--- a/app/controllers/epp/errors_controller.rb
+++ b/app/controllers/epp/errors_controller.rb
@@ -1,4 +1,6 @@
class Epp::ErrorsController < EppController
+ skip_authorization_check # TODO: remove it
+
def error
epp_errors << { code: params[:code], msg: params[:msg] }
render_epp_response '/epp/error'
diff --git a/app/controllers/epp/keyrelays_controller.rb b/app/controllers/epp/keyrelays_controller.rb
index f84694e5b..8a9b863d4 100644
--- a/app/controllers/epp/keyrelays_controller.rb
+++ b/app/controllers/epp/keyrelays_controller.rb
@@ -1,4 +1,6 @@
class Epp::KeyrelaysController < EppController
+ skip_authorization_check # TODO: remove it
+
# rubocop: disable Metrics/PerceivedComplexity
# rubocop: disable Metrics/CyclomaticComplexity
def keyrelay
diff --git a/app/controllers/epp/polls_controller.rb b/app/controllers/epp/polls_controller.rb
index 3376956e2..2f445abc6 100644
--- a/app/controllers/epp/polls_controller.rb
+++ b/app/controllers/epp/polls_controller.rb
@@ -1,4 +1,6 @@
class Epp::PollsController < EppController
+ skip_authorization_check # TODO: remove it
+
def poll
req_poll if params[:parsed_frame].css('poll').first['op'] == 'req'
ack_poll if params[:parsed_frame].css('poll').first['op'] == 'ack'
@@ -38,6 +40,6 @@ class Epp::PollsController < EppController
private
def validate_poll
- requires_attribute 'poll', 'op', values: %(ack req)
+ requires_attribute 'poll', 'op', values: %(ack req), allow_blank: true
end
end
diff --git a/app/controllers/epp/sessions_controller.rb b/app/controllers/epp/sessions_controller.rb
index 1485001a8..181cc19ac 100644
--- a/app/controllers/epp/sessions_controller.rb
+++ b/app/controllers/epp/sessions_controller.rb
@@ -1,12 +1,24 @@
class Epp::SessionsController < EppController
+ skip_authorization_check only: [:hello, :login, :logout]
+
def hello
render_epp_response('greeting')
end
+ # rubocop: disable Metrics/PerceivedComplexity
+ # rubocop: disable Metrics/CyclomaticComplexity
def login
- @api_user = ApiUser.find_by(login_params)
+ cert_valid = true
+ if request.ip == ENV['webclient_ip']
+ @api_user = ApiUser.find_by(login_params)
+ else
+ if request.env['HTTP_SSL_CLIENT_S_DN_CN'] != login_params[:username]
+ cert_valid = false
+ end
+ @api_user = ApiUser.find_by(login_params)
+ end
- if @api_user.try(:active)
+ if @api_user.try(:active) && cert_valid
epp_session[:api_user_id] = @api_user.id
render_epp_response('login_success')
else
@@ -14,6 +26,8 @@ class Epp::SessionsController < EppController
render_epp_response('login_fail')
end
end
+ # rubocop: enable Metrics/PerceivedComplexity
+ # rubocop: enable Metrics/CyclomaticComplexity
def logout
@api_user = current_user # cache current_user for logging
diff --git a/app/controllers/epp_controller.rb b/app/controllers/epp_controller.rb
index 28eff040f..a0985be4a 100644
--- a/app/controllers/epp_controller.rb
+++ b/app/controllers/epp_controller.rb
@@ -1,10 +1,23 @@
class EppController < ApplicationController
+ layout false
protect_from_forgery with: :null_session
+ skip_before_action :verify_authenticity_token
+
before_action :generate_svtrid
before_action :validate_request
- layout false
helper_method :current_user
+ rescue_from CanCan::AccessDenied do |_exception|
+ @errors ||= []
+ if @errors.blank?
+ @errors = [{
+ msg: t('errors.messages.epp_authorization_error'),
+ code: '2201'
+ }]
+ end
+ render_epp_response '/epp/error'
+ end
+
def generate_svtrid
# rubocop: disable Style/VariableName
@svTRID = "ccReg-#{format('%010d', rand(10**10))}"
@@ -84,15 +97,23 @@ class EppController < ApplicationController
# TODO: Add possibility to pass validations / options in the method
def requires(*selectors)
+ options = selectors.extract_options!
+ allow_blank = options[:allow_blank] ||= false # allow_blank is false by default
+
el, missing = nil, nil
selectors.each do |selector|
full_selector = [@prefix, selector].compact.join(' ')
+ attr = selector.split('>').last.strip.underscore
el = params[:parsed_frame].css(full_selector).first
- missing = el.nil?
+ if allow_blank
+ missing = el.nil?
+ else
+ missing = el.present? ? el.text.blank? : true
+ end
epp_errors << {
code: '2003',
- msg: I18n.t('errors.messages.required_parameter_missing', key: full_selector)
+ msg: I18n.t('errors.messages.required_parameter_missing', key: "#{full_selector} [#{attr}]")
} if missing
end
@@ -105,7 +126,7 @@ class EppController < ApplicationController
# requires_attribute 'transfer', 'op', values: %(approve, query, reject)
def requires_attribute(element_selector, attribute_selector, options)
- element = requires(element_selector)
+ element = requires(element_selector, allow_blank: options[:allow_blank])
return unless element
attribute = element[attribute_selector]
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index a6c1a9ff6..ff4f74517 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -1,4 +1,6 @@
class SessionsController < Devise::SessionsController
+ skip_authorization_check
+
def create
# TODO: Create ID Card login here:
# this is just testing config
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index cc61f56db..0c51ce5a7 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -8,4 +8,13 @@ module ApplicationHelper
return '' if unstable_env.nil?
"background-image: url(#{image_path(unstable_env.to_s + '.png')});"
end
+
+ def ident_indicator(contact)
+ case contact.ident_type
+ when 'birthday'
+ "[#{contact.ident_type}]"
+ else
+ "[#{contact.ident_country_code} #{contact.ident_type}]"
+ end
+ end
end
diff --git a/app/helpers/whodunnit_helper.rb b/app/helpers/whodunnit_helper.rb
deleted file mode 100644
index a1d2999c6..000000000
--- a/app/helpers/whodunnit_helper.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-module WhodunnitHelper
- def link_to_whodunnit(whodunnit)
- return nil unless whodunnit
- if whodunnit.include?('-ApiUser')
- user = ApiUser.find(whodunnit)
- return link_to(user.username, admin_epp_user_path(user))
- end
- user = AdminUser.find(whodunnit)
- return link_to(user.username, admin_user_path(user))
- rescue ActiveRecord::RecordNotFound
- return nil
- end
-
- def whodunnit_with_protocol(whodunnit)
- return nil unless whodunnit
- if whodunnit.include?('-ApiUser')
- user = ApiUser.find(whodunnit)
- return "#{user.username} (EPP)"
- end
- user = AdminUser.find(whodunnit)
- return user.username
- rescue ActiveRecord::RecordNotFound
- return nil
- end
-end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 47fc6c209..bb47bb2a8 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -2,16 +2,31 @@ class Ability
include CanCan::Ability
def initialize(user)
- alias_action :create, :read, :update, :destroy, to: :crud
+ alias_action :show, :create, :update, :destroy, to: :crud
@user = user || AdminUser.new
- @user.roles.each { |role| send(role) } if @user.roles
- return if @user.roles || @user.roles.any?
+ case @user.class.to_s
+ when 'AdminUser'
+ @user.roles.each { |role| send(role) } if @user.roles
+ when 'ApiUser'
+ epp
+ end
can :show, :dashboard
end
+ def epp
+ # Epp::Contact
+ can(:info, Epp::Contact) { |c, pw| c.registrar_id == @user.registrar_id || c.auth_info == pw }
+ can(:check, Epp::Contact)
+ can(:create, Epp::Contact)
+ can(:update, Epp::Contact) { |c, pw| c.registrar_id == @user.registrar_id && c.auth_info == pw }
+ can(:delete, Epp::Contact) { |c, pw| c.registrar_id == @user.registrar_id && c.auth_info == pw }
+ can(:renew, Epp::Contact)
+ can(:view_password, Epp::Contact) { |c| c.registrar_id == @user.registrar_id }
+ end
+
def user
can :show, :dashboard
end
@@ -30,6 +45,7 @@ class Ability
can :manage, DomainVersion
can :manage, User
can :manage, ApiUser
+ can :manage, Certificate
can :manage, Keyrelay
can :manage, LegalDocument
can :read, ApiLog::EppLog
diff --git a/app/models/api_user.rb b/app/models/api_user.rb
index fe0368125..d95ce8414 100644
--- a/app/models/api_user.rb
+++ b/app/models/api_user.rb
@@ -5,14 +5,24 @@ class ApiUser < User
# TODO: should have max request limit per day
belongs_to :registrar
has_many :contacts
+ has_many :certificates
validates :username, :password, :registrar, presence: true
validates :username, uniqueness: true
- before_save :create_crt, if: -> (au) { au.csr_changed? }
-
attr_accessor :registrar_typeahead
+ def ability
+ @ability ||= Ability.new(self)
+ end
+ delegate :can?, :cannot?, to: :ability
+
+ after_initialize :set_defaults
+ def set_defaults
+ return unless new_record?
+ self.active = true unless active_changed?
+ end
+
def registrar_typeahead
@registrar_typeahead || registrar || nil
end
@@ -24,28 +34,5 @@ class ApiUser < User
def queued_messages
registrar.messages.queued
end
-
- def create_crt
- csr_file = Tempfile.new('client_csr')
- csr_file.write(csr)
- csr_file.rewind
-
- crt_file = Tempfile.new('client_crt')
- _out, err, _st = Open3.capture3("openssl ca -keyfile #{APP_CONFIG['ca_key_path']} \
- -cert #{APP_CONFIG['ca_cert_path']} \
- -extensions usr_cert -notext -md sha256 \
- -in #{csr_file.path} -out #{crt_file.path} -key '#{APP_CONFIG['ca_key_password']}' -batch")
-
- if err.match(/Data Base Updated/)
- crt_file.rewind
- self.crt = crt_file.read
- return true
- else
- errors.add(:base, I18n.t('failed_to_create_certificate'))
- logger.error('FAILED TO CREATE CLIENT CERTIFICATE')
- logger.error(err)
- return false
- end
- end
end
# rubocop: enable Metrics/ClassLength
diff --git a/app/models/api_user_deprecated.rb b/app/models/api_user_deprecated.rb
index f44719fbb..c809564ea 100644
--- a/app/models/api_user_deprecated.rb
+++ b/app/models/api_user_deprecated.rb
@@ -32,10 +32,10 @@ class ApiUserDeprecated < ActiveRecord::Base
csr_file.rewind
crt_file = Tempfile.new('client_crt')
- _out, err, _st = Open3.capture3("openssl ca -keyfile #{APP_CONFIG['ca_key_path']} \
- -cert #{APP_CONFIG['ca_cert_path']} \
+ _out, err, _st = Open3.capture3("openssl ca -keyfile #{ENV['ca_key_path']} \
+ -cert #{ENV['ca_cert_path']} \
-extensions usr_cert -notext -md sha256 \
- -in #{csr_file.path} -out #{crt_file.path} -key '#{APP_CONFIG['ca_key_password']}' -batch")
+ -in #{csr_file.path} -out #{crt_file.path} -key '#{ENV['ca_key_password']}' -batch")
if err.match(/Data Base Updated/)
crt_file.rewind
diff --git a/app/models/certificate.rb b/app/models/certificate.rb
new file mode 100644
index 000000000..072d98076
--- /dev/null
+++ b/app/models/certificate.rb
@@ -0,0 +1,88 @@
+class Certificate < ActiveRecord::Base
+ include Versions
+
+ belongs_to :api_user
+
+ SIGNED = 'signed'
+ UNSIGNED = 'unsigned'
+ EXPIRED = 'expired'
+ REVOKED = 'revoked'
+ VALID = 'valid'
+
+ validates :csr, presence: true
+
+ def parsed_crt
+ @p_crt ||= OpenSSL::X509::Certificate.new(crt) if crt
+ end
+
+ def parsed_csr
+ @p_csr ||= OpenSSL::X509::Request.new(csr) if csr
+ end
+
+ def revoked?
+ status == REVOKED
+ end
+
+ def status
+ return UNSIGNED if crt.blank?
+ return @cached_status if @cached_status
+
+ @cached_status = SIGNED
+
+ if parsed_crt.not_before > Time.now.utc && parsed_crt.not_after < Time.now.utc
+ @cached_status = EXPIRED
+ end
+
+ crl = OpenSSL::X509::CRL.new(File.open(ENV['crl_path']).read)
+ return @cached_status unless crl.revoked.map(&:serial).include?(parsed_crt.serial)
+
+ @cached_status = REVOKED
+ end
+
+ def sign!
+ csr_file = Tempfile.new('client_csr')
+ csr_file.write(csr)
+ csr_file.rewind
+
+ crt_file = Tempfile.new('client_crt')
+ _out, err, _st = Open3.capture3("openssl ca -config #{ENV['openssl_config_path']} -keyfile #{ENV['ca_key_path']} \
+ -cert #{ENV['ca_cert_path']} \
+ -extensions usr_cert -notext -md sha256 \
+ -in #{csr_file.path} -out #{crt_file.path} -key '#{ENV['ca_key_password']}' -batch")
+
+ if err.match(/Data Base Updated/)
+ crt_file.rewind
+ self.crt = crt_file.read
+ save!
+ else
+ errors.add(:base, I18n.t('failed_to_create_certificate'))
+ logger.error('FAILED TO CREATE CLIENT CERTIFICATE')
+ logger.error(err)
+ return false
+ end
+ end
+
+ def revoke!
+ crt_file = Tempfile.new('client_crt')
+ crt_file.write(crt)
+ crt_file.rewind
+
+ _out, err, _st = Open3.capture3("openssl ca -config #{ENV['openssl_config_path']} -keyfile #{ENV['ca_key_path']} \
+ -cert #{ENV['ca_cert_path']} \
+ -revoke #{crt_file.path} -key '#{ENV['ca_key_password']}' -batch")
+
+ if err.match(/Data Base Updated/) || err.match(/ERROR:Already revoked/)
+ save!
+ @cached_status = REVOKED
+ else
+ errors.add(:base, I18n.t('failed_to_revoke_certificate'))
+ logger.error('FAILED TO REVOKE CLIENT CERTIFICATE')
+ logger.error(err)
+ return false
+ end
+
+ _out, _err, _st = Open3.capture3("openssl ca -config #{ENV['openssl_config_path']} -keyfile #{ENV['ca_key_path']} \
+ -cert #{ENV['ca_cert_path']} \
+ -gencrl -out #{ENV['crl_path']} -key '#{ENV['ca_key_password']}' -batch")
+ end
+end
diff --git a/app/models/concerns/epp_errors.rb b/app/models/concerns/epp_errors.rb
index 4d95cea27..cf3824260 100644
--- a/app/models/concerns/epp_errors.rb
+++ b/app/models/concerns/epp_errors.rb
@@ -3,42 +3,43 @@ module EppErrors
def construct_epp_errors
epp_errors = []
- errors.messages.each do |key, values|
- key = key.to_s.split('.')[0].to_sym
- next if key == :epp_errors
+ errors.messages.each do |attr, errors|
+ attr = attr.to_s.split('.')[0].to_sym
+ next if attr == :epp_errors
- if self.class.reflect_on_association(key)
- epp_errors << collect_child_errors(key)
+ if self.class.reflect_on_association(attr)
+ epp_errors << collect_child_errors(attr)
end
- epp_errors << collect_parent_errors(values)
+ epp_errors << collect_parent_errors(attr, errors)
end
errors[:epp_errors] = epp_errors
errors[:epp_errors].flatten!
end
- def collect_parent_errors(values)
- epp_errors = []
- values = [values] if values.is_a?(String)
+ def collect_parent_errors(attr, errors)
+ errors = [errors] if errors.is_a?(String)
- values.each do |err|
+ epp_errors = []
+ errors.each do |err|
code, value = find_epp_code_and_value(err)
next unless code
- epp_errors << { code: code, msg: err, value: value }
+ msg = attr.to_sym == :base ? err : "#{err} [#{attr}]"
+ epp_errors << { code: code, msg: msg, value: value }
end
epp_errors
end
- def collect_child_errors(key)
- macro = self.class.reflect_on_association(key).macro
+ def collect_child_errors(attr)
+ macro = self.class.reflect_on_association(attr).macro
multi = [:has_and_belongs_to_many, :has_many]
# single = [:belongs_to, :has_one]
epp_errors = []
- send(key).each do |x|
- x.errors.messages.each do |_key, values|
- epp_errors << x.collect_parent_errors(values)
+ send(attr).each do |x|
+ x.errors.messages.each do |attribute, errors|
+ epp_errors << x.collect_parent_errors(attribute, errors)
end
end if multi.include?(macro)
diff --git a/app/models/concerns/version_session.rb b/app/models/concerns/version_session.rb
index 50095f2c1..4d455d784 100644
--- a/app/models/concerns/version_session.rb
+++ b/app/models/concerns/version_session.rb
@@ -5,7 +5,7 @@ module VersionSession
before_save :add_session
def add_session
- self.session = PaperSession.session
+ self.session = ::PaperSession.session
true
end
end
diff --git a/app/models/concerns/versions.rb b/app/models/concerns/versions.rb
index d14501e74..8918647f1 100644
--- a/app/models/concerns/versions.rb
+++ b/app/models/concerns/versions.rb
@@ -28,9 +28,9 @@ module Versions
return nil if creator_str.blank?
if creator_str =~ /^\d-api-/
- ApiUser.find(creator_str)
+ ApiUser.find_by(id: creator_str)
else
- AdminUser.find(creator_str)
+ AdminUser.find_by(id: creator_str)
end
end
@@ -38,9 +38,9 @@ module Versions
return nil if updator_str.blank?
if updator_str =~ /^\d-api-/
- ApiUser.find(updator_str)
+ ApiUser.find_by(id: updator_str)
else
- AdminUser.find(updator_str)
+ AdminUser.find_by(id: updator_str)
end
end
diff --git a/app/models/contact.rb b/app/models/contact.rb
index 4238924b0..da8a3f651 100644
--- a/app/models/contact.rb
+++ b/app/models/contact.rb
@@ -1,6 +1,5 @@
class Contact < ActiveRecord::Base
include Versions # version/contact_version.rb
- include EppErrors
has_one :address, dependent: :destroy
has_one :disclosure, class_name: 'ContactDisclosure', dependent: :destroy
@@ -8,45 +7,46 @@ class Contact < ActiveRecord::Base
has_many :domain_contacts
has_many :domains, through: :domain_contacts
has_many :statuses, class_name: 'ContactStatus'
+ has_many :legal_documents, as: :documentable
belongs_to :registrar
- accepts_nested_attributes_for :address, :disclosure
+ accepts_nested_attributes_for :address, :disclosure, :legal_documents
validates :name, :phone, :email, :ident, :address, :registrar, :ident_type, presence: true
# Phone nr validation is very minimam in order to support legacy requirements
validates :phone, format: /\+[0-9]{1,3}\.[0-9]{1,14}?/
validates :email, format: /@/
- validates :ident, format: /\d{4}-\d{2}-\d{2}/, if: proc { |c| c.ident_type == 'birthday' }
+ validates :ident,
+ format: { with: /\d{4}-\d{2}-\d{2}/, message: :invalid_birthday_format },
+ if: proc { |c| c.ident_type == 'birthday' }
+ validates :ident_country_code, presence: true, if: proc { |c| %w(bic priv).include? c.ident_type }
+ validates :code,
+ uniqueness: { message: :epp_id_taken },
+ format: { with: /\A[\w\-\:]*\Z/i },
+ length: { maximum: 100 }
- validate :ident_must_be_valid
+ validate :ident_valid_format?
- validates :code, uniqueness: { message: :epp_id_taken }
+ delegate :street, to: :address
+ delegate :city, to: :address
+ delegate :zip, to: :address
+ delegate :state, to: :address
+ delegate :country_code, to: :address
+ delegate :country, to: :address
- delegate :city, to: :address # , prefix: true
- delegate :street, to: :address # , prefix: true
- delegate :zip, to: :address # , prefix: true
-
- # callbacks
- # TODO: remove old
- # after_commit :domains_snapshot
- # after_update :domains_snapshot
- # after_destroy :domains_snapshot
+ before_validation :set_ident_country_code
before_create :generate_code
before_create :generate_auth_info
after_create :ensure_disclosure
- # scopes
scope :current_registrars, ->(id) { where(registrar_id: id) }
- IDENT_TYPE_ICO = 'ico'
+ IDENT_TYPE_BIC = 'bic'
IDENT_TYPES = [
- IDENT_TYPE_ICO, # Company registry code (or similar)
- 'bic', # Business registry code
+ IDENT_TYPE_BIC, # Company registry code (or similar)
'priv', # National idendtification number
- 'op', # Estonian ID, depricated
- 'passport', # Passport number, depricated
'birthday' # Birthday date
]
@@ -54,124 +54,10 @@ class Contact < ActiveRecord::Base
CONTACT_TYPE_ADMIN = 'admin'
CONTACT_TYPES = [CONTACT_TYPE_TECH, CONTACT_TYPE_ADMIN]
- def ident_must_be_valid
- # TODO: Ident can also be passport number or company registry code.
- # so have to make changes to validations (and doc/schema) accordingly
- return true unless ident.present? && ident_type.present? && ident_type == 'op'
- code = Isikukood.new(ident)
- errors.add(:ident, 'bad format') unless code.valid?
- end
-
- def ensure_disclosure
- create_disclosure! unless disclosure
- end
-
- # TODO: remove old
- # def domains_snapshot
- # (domains + domains_owned).uniq.each do |domain|
- # next unless domain.is_a?(Domain)
- # # next if domain.versions.last == domain.create_snapshot
- # domain.create_version # Method from paper_trail
- # end
- # end
-
- def juridical?
- ident_type == IDENT_TYPE_ICO
- end
-
- def citizen?
- ident_type != IDENT_TYPE_ICO
- end
-
- def cr_id
- # created_by ? created_by.username : nil
- end
-
- def up_id
- # updated_by ? updated_by.username : nil
- end
-
- def auth_info_matches(pw)
- auth_info == pw
- end
-
- # generate random id for contact
- def generate_code
- self.code = SecureRandom.hex(4)
- end
-
- def generate_auth_info
- self.auth_info = SecureRandom.hex(16)
- end
-
- # Find a way to use self.domains with contact
- def domains_owned
- Domain.where(owner_contact_id: id)
- end
-
- def relations_with_domain?
- return true if domain_contacts.present? || domains_owned.present?
- false
- end
-
- # should use only in transaction
- def destroy_and_clean
- if relations_with_domain?
- errors.add(:domains, :exist)
- return false
- end
- destroy
- end
-
- def epp_code_map # rubocop:disable Metrics/MethodLength
- {
- '2302' => [ # Object exists
- [:code, :epp_id_taken]
- ],
- '2305' => [ # Association exists
- [:domains, :exist]
- ],
- '2005' => [ # Value syntax error
- [:phone, :invalid],
- [:email, :invalid],
- [:ident, :invalid]
- ]
- }
- end
-
- def to_s
- name
- end
-
- # TODO: remove old
- # for archiving
- # def snapshot
- # {
- # name: name,
- # phone: phone,
- # code: code,
- # ident: ident,
- # email: email
- # }
- # end
-
class << self
- # non-EPP
-
- # EPP
- def extract_attributes(ph, _type = :create)
- ph[:postalInfo] = ph[:postalInfo].first if ph[:postalInfo].is_a?(Array)
- contact_hash = {
- phone: ph[:voice],
- ident: ph[:ident],
- ident_type: ph[:ident_type],
- email: ph[:email],
- fax: ph[:fax],
- name: ph[:postalInfo].try(:[], :name),
- org_name: ph[:postalInfo].try(:[], :org)
- }
- # contact_hash[:auth_info] = ph[:authInfo][:pw] if type == :create
- contact_hash.delete_if { |_k, v| v.nil? }
+ def search_by_query(query)
+ res = search(code_cont: query).result
+ res.reduce([]) { |o, v| o << { id: v[:id], display_key: "#{v.name} (#{v.code})" } }
end
def check_availability(codes)
@@ -188,10 +74,84 @@ class Contact < ActiveRecord::Base
res
end
+ end
- def search_by_query(query)
- res = search(code_cont: query).result
- res.reduce([]) { |o, v| o << { id: v[:id], display_key: "#{v.name} (#{v.code})" } }
+ def to_s
+ name
+ end
+
+ def ident_valid_format?
+ case ident_type
+ when 'priv'
+ case ident_country_code
+ when 'EE'
+ code = Isikukood.new(ident)
+ errors.add(:ident, :invalid_EE_identity_format) unless code.valid?
+ end
+ end
+ end
+
+ def ensure_disclosure
+ create_disclosure! unless disclosure
+ end
+
+ def bic?
+ ident_type == IDENT_TYPE_BIC
+ end
+
+ def priv?
+ ident_type != IDENT_TYPE_BIC
+ end
+
+ def generate_code
+ self.code = SecureRandom.hex(4) if code.blank?
+ end
+
+ def generate_auth_info
+ return if @generate_auth_info_disabled
+ self.auth_info = SecureRandom.hex(16)
+ end
+
+ def disable_generate_auth_info! # needed for testing
+ @generate_auth_info_disabled = true
+ end
+
+ def auth_info=(pw)
+ self[:auth_info] = pw if new_record?
+ end
+
+ def code=(code)
+ self[:code] = code if new_record?
+ end
+
+ # Find a way to use self.domains with contact
+ def domains_owned
+ Domain.where(owner_contact_id: id)
+ end
+
+ def relations_with_domain?
+ return true if domain_contacts.present? || domains_owned.present?
+ false
+ end
+
+ # TODO: refactor, it should not allow to destroy with normal destroy,
+ # no need separate method
+ # should use only in transaction
+ def destroy_and_clean
+ if relations_with_domain?
+ errors.add(:domains, :exist)
+ return false
+ end
+ destroy
+ end
+
+ def set_ident_country_code
+ return true unless ident_country_code_changed? && ident_country_code.present?
+ code = Country.new(ident_country_code)
+ if code
+ self.ident_country_code = code.alpha2
+ else
+ errors.add(:ident_country_code, 'is not following ISO_3166-1 alpha 2 format')
end
end
end
diff --git a/app/models/dnskey.rb b/app/models/dnskey.rb
index bb194959a..fbdeb80ec 100644
--- a/app/models/dnskey.rb
+++ b/app/models/dnskey.rb
@@ -85,9 +85,9 @@ class Dnskey < ActiveRecord::Base
end
def generate_ds_key_tag
- public_key.gsub!(' ', '')
+ pk = public_key.gsub(' ', '')
wire_format = [flags, protocol, alg].pack('S!>CC')
- wire_format += Base64.decode64(public_key)
+ wire_format += Base64.decode64(pk)
c = 0
wire_format.each_byte.with_index do |b, i|
diff --git a/app/models/domain.rb b/app/models/domain.rb
index 3ca9e0f51..b6a0b6faa 100644
--- a/app/models/domain.rb
+++ b/app/models/domain.rb
@@ -20,8 +20,6 @@ class Domain < ActiveRecord::Base
-> { where(domain_contacts: { contact_type: DomainContact::ADMIN }) },
through: :domain_contacts, source: :contact
- # TODO: remove old
- # has_many :nameservers, dependent: :delete_all, after_add: :track_nameserver_add
has_many :nameservers, dependent: :delete_all
accepts_nested_attributes_for :nameservers, allow_destroy: true,
@@ -43,11 +41,11 @@ class Domain < ActiveRecord::Base
has_many :legal_documents, as: :documentable
accepts_nested_attributes_for :legal_documents, reject_if: proc { |attrs| attrs[:body].blank? }
- delegate :code, to: :owner_contact, prefix: true
+ delegate :code, to: :owner_contact, prefix: true
delegate :email, to: :owner_contact, prefix: true
delegate :ident, to: :owner_contact, prefix: true
delegate :phone, to: :owner_contact, prefix: true
- delegate :name, to: :registrar, prefix: true
+ delegate :name, to: :registrar, prefix: true
before_create :generate_auth_info
before_create :set_validity_dates
@@ -118,11 +116,6 @@ class Domain < ActiveRecord::Base
attr_accessor :owner_contact_typeahead, :update_me
- # TODO: remove old
- # archiving
- # if proc works only on changes on domain sadly
- # has_paper_trail class_name: 'DomainVersion', meta: { snapshot: :create_snapshot }, if: proc(&:new_version)
-
def tech_domain_contacts
domain_contacts.select { |x| x.contact_type == DomainContact::TECH }
end
@@ -131,52 +124,6 @@ class Domain < ActiveRecord::Base
domain_contacts.select { |x| x.contact_type == DomainContact::ADMIN }
end
- # TODO: remove old
- # def new_version
- # return false if versions.try(:last).try(:snapshot) == create_snapshot
- # true
- # end
-
- # TODO: remove old
- # def create_version
- # return true unless PaperTrail.enabled?
- # return true unless valid?
- # touch_with_version if new_version
- # end
-
- # TODO: remove old
- # def track_nameserver_add(_nameserver)
- # return true if versions.count == 0
- # return true unless valid? && new_version
-
- # touch_with_version
- # end
-
- # TODO: remove old
- # def create_snapshot
- # oc = owner_contact.snapshot if owner_contact.is_a?(Contact)
- # {
- # owner_contact: oc,
- # tech_contacts: tech_contacts.map(&:snapshot),
- # admin_contacts: admin_contacts.map(&:snapshot),
- # nameservers: nameservers.map(&:snapshot),
- # domain: make_snapshot
- # }.to_yaml
- # end
-
- # TODO: remove old
- # def make_snapshot
- # {
- # name: name,
- # status: status,
- # period: period,
- # period_unit: period_unit,
- # registrar_id: registrar.try(:id),
- # valid_to: valid_to,
- # valid_from: valid_from
- # }
- # end
-
def name=(value)
value.strip!
value.downcase!
@@ -265,7 +212,7 @@ class Domain < ActiveRecord::Base
attach_contact(DomainContact::TECH, owner_contact)
end
- return unless admin_domain_contacts.count.zero? && owner_contact.citizen?
+ return unless admin_domain_contacts.count.zero? && owner_contact.priv?
attach_contact(DomainContact::ADMIN, owner_contact)
end
@@ -305,36 +252,36 @@ class Domain < ActiveRecord::Base
# rubocop:disable Metrics/MethodLength
def update_whois_body
self.whois_body = <<-EOS
- This Whois Server contains information on
- Estonian Top Level Domain ee TLD
+ This Whois Server contains information on
+ Estonian Top Level Domain ee TLD
- domain: #{name}
- registrar: #{registrar}
- status:
- registered:
- changed: #{updated_at.to_s(:db)}
- expire:
- outzone:
- delete:
+ domain: #{name}
+ registrar: #{registrar}
+ status:
+ registered:
+ changed: #{updated_at.to_s(:db)}
+ expire:
+ outzone:
+ delete:
- contact
- name:
- e-mail:
- registrar:
- created:
+ contact
+ name:
+ e-mail:
+ registrar:
+ created:
- contact:
+ contact:
- nsset:
- nserver:
+ nsset:
+ nserver:
- registrar:
- org:
- url:
- phone:
- address:
- created:
- changed:
+ registrar:
+ org:
+ url:
+ phone:
+ address:
+ created:
+ changed:
EOS
end
# rubocop:enabled Metrics/MethodLength
diff --git a/app/models/epp/contact.rb b/app/models/epp/contact.rb
new file mode 100644
index 000000000..d9df7f2ae
--- /dev/null
+++ b/app/models/epp/contact.rb
@@ -0,0 +1,102 @@
+# rubocop: disable Metrics/ClassLength
+class Epp::Contact < Contact
+ include EppErrors
+
+ # disable STI, there is type column present
+ self.inheritance_column = :sti_disabled
+
+ class << self
+ # rubocop: disable Metrics/PerceivedComplexity
+ # rubocop: disable Metrics/CyclomaticComplexity
+ # rubocop: disable Metrics/MethodLength
+ def attrs_from(frame)
+ f = frame
+ at = {}.with_indifferent_access
+ at[:name] = f.css('postalInfo name').text if f.css('postalInfo name').present?
+ at[:org_name] = f.css('postalInfo org').text if f.css('postalInfo org').present?
+ at[:email] = f.css('email').text if f.css('email').present?
+ at[:fax] = f.css('fax').text if f.css('fax').present?
+ at[:phone] = f.css('voice').text if f.css('voice').present?
+ at[:auth_info] = f.css('authInfo pw').text if f.css('authInfo pw').present?
+
+ if f.css('ident').present? && f.css('ident').attr('type').present?
+ at[:ident] = f.css('ident').text
+ at[:ident_type] = f.css('ident').attr('type').try(:text)
+ at[:ident_country_code] = f.css('ident').attr('cc').try(:text)
+ end
+
+ at[:address_attributes] = {}.with_indifferent_access
+ sat = at[:address_attributes]
+ sat[:city] = f.css('postalInfo addr city').text if f.css('postalInfo addr city').present?
+ sat[:zip] = f.css('postalInfo addr pc').text if f.css('postalInfo addr pc').present?
+ sat[:street] = f.css('postalInfo addr street').text if f.css('postalInfo addr street').present?
+ sat[:state] = f.css('postalInfo addr sp').text if f.css('postalInfo addr sp').present?
+ sat[:country_code] = f.css('postalInfo addr cc').text if f.css('postalInfo addr cc').present?
+ at.delete(:address_attributes) if at[:address_attributes].blank?
+
+ legal_frame = f.css('legalDocument').first
+ if legal_frame.present?
+ at[:legal_documents_attributes] = legal_document_attrs(legal_frame)
+ end
+
+ at
+ end
+ # rubocop: enable Metrics/MethodLength
+ # rubocop: enable Metrics/PerceivedComplexity
+ # rubocop: enable Metrics/CyclomaticComplexity
+
+ def new(frame, registrar)
+ return super if frame.blank?
+
+ custom_code =
+ if frame.css('id').present?
+ "#{registrar.code}:#{frame.css('id').text.parameterize}"
+ else
+ nil
+ end
+
+ super(
+ attrs_from(frame).merge(
+ code: custom_code,
+ registrar: registrar
+ )
+ )
+ end
+
+ def legal_document_attrs(legal_frame)
+ [{
+ body: legal_frame.text,
+ document_type: legal_frame['type']
+ }]
+ end
+ end
+
+ def epp_code_map # rubocop:disable Metrics/MethodLength
+ {
+ '2302' => [ # Object exists
+ [:code, :epp_id_taken]
+ ],
+ '2305' => [ # Association exists
+ [:domains, :exist]
+ ],
+ '2005' => [ # Value syntax error
+ [:phone, :invalid],
+ [:email, :invalid],
+ [:ident, :invalid],
+ [:ident, :invalid_EE_identity_format],
+ [:ident, :invalid_birthday_format]
+ ]
+ }
+ end
+
+ def update_attributes(frame)
+ return super if frame.blank?
+ at = {}.with_indifferent_access
+ at.deep_merge!(self.class.attrs_from(frame.css('chg')))
+ legal_frame = frame.css('legalDocument').first
+ at[:legal_documents_attributes] = self.class.legal_document_attrs(legal_frame)
+
+ super(at)
+ end
+end
+# rubocop: enable Metrics/ClassLength
diff --git a/app/models/epp/epp_domain.rb b/app/models/epp/epp_domain.rb
index 0cd728499..75c348afe 100644
--- a/app/models/epp/epp_domain.rb
+++ b/app/models/epp/epp_domain.rb
@@ -146,7 +146,7 @@ class Epp::EppDomain < Domain
next
end
- if k == :admin && contact.juridical?
+ if k == :admin && contact.bic?
add_epp_error('2306', 'contact', x[:contact], [:domain_contacts, :admin_contact_can_be_only_citizen])
next
end
diff --git a/app/models/registrar.rb b/app/models/registrar.rb
index 219e5d06d..e895273b3 100644
--- a/app/models/registrar.rb
+++ b/app/models/registrar.rb
@@ -9,10 +9,18 @@ class Registrar < ActiveRecord::Base
validates :name, :reg_no, :country_code, :email, presence: true
validates :name, :reg_no, uniqueness: true
+ validate :set_code, if: :new_record?
after_save :touch_domains_version
validates :email, :billing_email, format: /@/, allow_blank: true
+ class << self
+ def search_by_query(query)
+ res = search(name_or_reg_no_cont: query).result
+ res.reduce([]) { |o, v| o << { id: v[:id], display_key: "#{v[:name]} (#{v[:reg_no]})" } }
+ end
+ end
+
def domain_transfers
at = DomainTransfer.arel_table
DomainTransfer.where(
@@ -23,7 +31,7 @@ class Registrar < ActiveRecord::Base
end
def address
- [street, city, state, zip].reject(&:empty?).compact.join(', ')
+ [street, city, state, zip].reject(&:blank?).compact.join(', ')
end
def to_s
@@ -34,10 +42,23 @@ class Registrar < ActiveRecord::Base
Country.new(country_code)
end
- class << self
- def search_by_query(query)
- res = search(name_or_reg_no_cont: query).result
- res.reduce([]) { |o, v| o << { id: v[:id], display_key: "#{v[:name]} (#{v[:reg_no]})" } }
+ def code=(code)
+ self[:code] = code if new_record?
+ end
+
+ private
+
+ def set_code
+ return false if name.blank?
+ new_code = name.parameterize
+
+ # ensure code is always uniq automatically for a new record
+ seq = 1
+ while self.class.find_by_code(new_code)
+ new_code += seq.to_s
+ seq += 1
end
+
+ self.code = new_code
end
end
diff --git a/app/models/version/certificate_version.rb b/app/models/version/certificate_version.rb
new file mode 100644
index 000000000..bcc89e62a
--- /dev/null
+++ b/app/models/version/certificate_version.rb
@@ -0,0 +1,4 @@
+class CertificateVersion < PaperTrail::Version
+ self.table_name = :log_certificates
+ self.sequence_name = :log_certificates_id_seq
+end
diff --git a/app/models/zonefile_setting.rb b/app/models/zonefile_setting.rb
index cdeb8087d..c9cac6154 100644
--- a/app/models/zonefile_setting.rb
+++ b/app/models/zonefile_setting.rb
@@ -18,7 +18,7 @@ class ZonefileSetting < ActiveRecord::Base
"select generate_zonefile('#{origin}')"
)[0]['generate_zonefile']
- File.open("#{APP_CONFIG['zonefile_export_dir']}/#{filename}", 'w') { |f| f.write(zf) }
+ File.open("#{ENV['zonefile_export_dir']}/#{filename}", 'w') { |f| f.write(zf) }
STDOUT << "#{Time.now.utc} - Successfully generated zonefile #{filename}\n"
end
diff --git a/app/views/admin/api_users/_form.haml b/app/views/admin/api_users/_form.haml
index b8fd1071f..29f8b1179 100644
--- a/app/views/admin/api_users/_form.haml
+++ b/app/views/admin/api_users/_form.haml
@@ -7,7 +7,7 @@
%hr
.row
- .col-md-6
+ .col-md-12
.form-group
= f.label :username
= f.text_field(:username, class: 'form-control')
@@ -26,11 +26,6 @@
%label{for: 'api_user_active'}
= f.check_box(:active)
= t('active')
-
- .col-md-6.text-left
- .form-group
- = f.label :csr, t('certificate_signing_req')
- = f.file_field :csr
%hr
.row
.col-md-12.text-right
diff --git a/app/views/admin/api_users/show.haml b/app/views/admin/api_users/show.haml
index 63ffc3952..fc798370e 100644
--- a/app/views/admin/api_users/show.haml
+++ b/app/views/admin/api_users/show.haml
@@ -15,7 +15,7 @@
- if @api_user.errors.any?
%hr
.row
- .col-md-6
+ .col-md-12
.panel.panel-default
.panel-heading
%h3.panel-title= t('general')
@@ -29,21 +29,24 @@
%dt= t('active')
%dd= @api_user.active
-
- .col-md-6
+.row
+ .col-md-12
.panel.panel-default
- .panel-heading
- %h3.panel-title= t('certificates')
- .panel-body
- %dl.dl-horizontal
- %dt= t('csr')
- - if @api_user.csr
- %dd= link_to(t('download'), download_csr_admin_api_user_path)
- - else
- %dd -
+ .panel-heading.clearfix
+ .pull-left
+ = t('certificates')
+ .pull-right
+ = link_to(t('upload_csr'), new_admin_api_user_certificate_path(@api_user), class: 'btn btn-primary btn-xs')
- %dt= t('crt')
- - if @api_user.csr
- %dd= link_to(t('download'), download_crt_admin_api_user_path)
- - else
- %dd -
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-10'}= t('subject')
+ %th{class: 'col-xs-2'}= t('status')
+ %tbody
+ - @api_user.certificates.each do |x|
+ - if x.csr
+ %tr
+ %td= link_to(x.parsed_csr.try(:subject), admin_api_user_certificate_path(@api_user, x))
+ %td= x.status
diff --git a/app/views/admin/certificates/new.haml b/app/views/admin/certificates/new.haml
new file mode 100644
index 000000000..f0c1fe7ce
--- /dev/null
+++ b/app/views/admin/certificates/new.haml
@@ -0,0 +1,20 @@
+%h2= t('upload_csr')
+%hr
+= form_for([:admin, @api_user, @certificate], multipart: true) do |f|
+ - if @certificate.errors.any?
+ - @certificate.errors.each do |attr, err|
+ = err
+ %br
+ - if @certificate.errors.any?
+ %hr
+
+ .row
+ .col-md-12.text-left
+ .form-group
+ = f.label :csr, t('certificate_signing_req')
+ = f.file_field :csr
+ %hr
+ .row
+ .col-md-12.text-right
+ = button_tag(t('save'), class: 'btn btn-primary')
+
diff --git a/app/views/admin/certificates/show.haml b/app/views/admin/certificates/show.haml
new file mode 100644
index 000000000..b03bcdc4d
--- /dev/null
+++ b/app/views/admin/certificates/show.haml
@@ -0,0 +1,75 @@
+.row
+ .col-sm-6
+ %h2.text-center-xs
+ = t('certificates')
+ .col-sm-6
+ %h2.text-right.text-center-xs
+ = link_to(t('back_to_api_user'), [:admin, @api_user], class: 'btn btn-default')
+
+%hr
+- if @certificate.errors.any?
+ - @certificate.errors.each do |attr, err|
+ = err
+ %br
+- if @certificate.errors.any?
+ %hr
+.row
+ .col-md-12
+ .panel.panel-default
+ .panel-heading.clearfix
+ .pull-left
+ = t('csr')
+ .pull-right
+ = link_to(t('download'), download_csr_admin_api_user_certificate_path(@api_user, @certificate), class: 'btn btn-default btn-xs')
+ - unless @crt
+ = link_to(t('sign_this_request'), sign_admin_api_user_certificate_path(@api_user, @certificate), method: :post, class: 'btn btn-primary btn-xs')
+
+ .panel-body
+ %dl.dl-horizontal
+ %dt= t('version')
+ %dd= @csr.version
+
+ %dt= t('subject')
+ %dd= @csr.subject
+
+ %dt= t('signature_algorithm')
+ %dd= @csr.signature_algorithm
+
+- if @crt
+ .row
+ .col-md-12
+ .panel.panel-default
+ .panel-heading.clearfix
+ .pull-left
+ = t('crt') unless @certificate.revoked?
+ = t('crt_revoked') if @certificate.revoked?
+ .pull-right
+ = link_to(t('download'), download_crt_admin_api_user_certificate_path(@api_user, @certificate), class: 'btn btn-default btn-xs')
+ - unless @certificate.revoked?
+ = link_to(t('revoke_this_certificate'), revoke_admin_api_user_certificate_path(@api_user, @certificate), method: :post, class: 'btn btn-primary btn-xs')
+ - if @crt
+ .panel-body
+ %dl.dl-horizontal
+ %dt= t('version')
+ %dd= @crt.version
+
+ %dt= t('serial_number')
+ %dd= @crt.serial
+
+ %dt= t('signature_algorithm')
+ %dd= @crt.signature_algorithm
+
+ %dt= t('issuer')
+ %dd= @crt.issuer
+
+ %dt= t('valid_from')
+ %dd= @crt.not_before
+
+ %dt= t('valid_to')
+ %dd= @crt.not_after
+
+ %dt= t('subject')
+ %dd= @crt.subject
+
+ %dt= t('extensions')
+ %dd= @crt.extensions.map(&:to_s).join('
').html_safe
diff --git a/app/views/admin/contacts/index.haml b/app/views/admin/contacts/index.haml
index 7c27cf646..3f437d62d 100644
--- a/app/views/admin/contacts/index.haml
+++ b/app/views/admin/contacts/index.haml
@@ -22,20 +22,20 @@
%thead
%tr
%th{class: 'col-xs-2'}
- = sort_link(@q, 'name', t('name'))
+ = sort_link(@q, 'name', t(:name))
%th{class: 'col-xs-2'}
- = sort_link(@q, 'code', t('code'))
+ = sort_link(@q, 'ident', t(:identity))
%th{class: 'col-xs-2'}
- = sort_link(@q, 'ident', t('identity_code'))
+ = sort_link(@q, 'email', t(:email))
%th{class: 'col-xs-2'}
- = sort_link(@q, 'email', t('email'))
+ = sort_link(@q, 'code', t(:code))
%tbody
- - @contacts.each do |x|
+ - @contacts.each do |contact|
%tr
- %td= link_to(x, admin_contact_path(x))
- %td= x.code
- %td= x.ident
- %td= x.email
+ %td= link_to(contact, admin_contact_path(contact))
+ %td= "#{contact.ident} #{ident_indicator(contact)}"
+ %td= contact.email
+ %td= contact.code
.row
.col-md-12
= paginate @contacts
diff --git a/app/views/admin/contacts/partials/_address.haml b/app/views/admin/contacts/partials/_address.haml
index 1d27ba7bd..aecba9a70 100644
--- a/app/views/admin/contacts/partials/_address.haml
+++ b/app/views/admin/contacts/partials/_address.haml
@@ -1,28 +1,24 @@
.panel.panel-default
.panel-heading
- %h3.panel-title= t('address')
+ %h3.panel-title= t(:address)
.panel-body
- unless @contact.address.nil?
%dl.dl-horizontal
- %dt= t('country')
- %dd= @contact.address.country
+ - if @contact.bic?
+ %dt= t(:org_name)
+ %dd= @contact.org_name
- %dt= t('city')
- %dd= @contact.address.city
+ %dt= t(:street)
+ %dd= @contact.street
- %dt= t('street')
- %dd= @contact.address.street
+ %dt= t(:city)
+ %dd= @contact.city
- - if @contact.address.street2
- %dt= t('street')
- %dd= @contact.address.street2
+ %dt= t(:zip)
+ %dd= @contact.zip
- - if @contact.address.street3
- %dt= t('street')
- %dd= @contact.address.street3
-
-
-
- %dt= t('zip')
- %dd= @contact.address.zip
+ %dt= t(:state)
+ %dd= @contact.state
+ %dt= t(:country)
+ %dd= @contact.country
diff --git a/app/views/admin/contacts/partials/_general.haml b/app/views/admin/contacts/partials/_general.haml
index d5cc42044..2911ab783 100644
--- a/app/views/admin/contacts/partials/_general.haml
+++ b/app/views/admin/contacts/partials/_general.haml
@@ -3,30 +3,25 @@
%h3.panel-title= t('general')
.panel-body
%dl.dl-horizontal
- %dt= t('name')
- %dd= @contact.name
+ %dt= t(:ident)
+ %dd= "#{@contact.ident} #{ident_indicator(@contact)}"
- %dt= t('org_name')
- %dd= @contact.org_name
+ %br
- %dt= t('code')
- %dd= @contact.code
-
- %dt= t('ident')
- %dd= @contact.ident
-
- %dt= t('ident_type')
- %dd= @contact.ident_type
-
- %dt= t('email')
+ %dt= t(:email)
%dd= @contact.email
- %dt= t('phone')
+ %dt= t(:phone)
%dd= @contact.phone
- if @contact.fax
- %dt= t('fax')
+ %dt= t(:fax)
%dd= @contact.fax
+ %br
+
+ %dt= t(:code)
+ %dd= @contact.code
+
%dt= t('password')
%dd= @contact.auth_info
diff --git a/app/views/admin/contacts/show.haml b/app/views/admin/contacts/show.haml
index d5620bb7c..dba7dd39a 100644
--- a/app/views/admin/contacts/show.haml
+++ b/app/views/admin/contacts/show.haml
@@ -1,10 +1,13 @@
.row
.col-sm-12
%h2.text-center-xs
- = "#{t('contact_details')}"
+ = @contact.name
%hr
.row
.col-md-6= render 'admin/contacts/partials/general'
.col-md-6= render 'admin/contacts/partials/address'
.row
.col-md-12= render 'admin/contacts/partials/domains'
+.row
+ .col-md-12
+ = render 'admin/domains/partials/legal_documents', legal_documents: @contact.legal_documents
diff --git a/app/views/admin/domains/partials/_legal_documents.haml b/app/views/admin/domains/partials/_legal_documents.haml
index b9fe5144e..5a25ae325 100644
--- a/app/views/admin/domains/partials/_legal_documents.haml
+++ b/app/views/admin/domains/partials/_legal_documents.haml
@@ -8,7 +8,7 @@
%th{class: 'col-xs-8'}= t('created_at')
%th{class: 'col-xs-4'}= t('type')
%tbody
- - @domain.legal_documents.each do |x|
+ - legal_documents.each do |x|
%tr
%td= link_to(x.created_at, [:admin, x])
%td= x.document_type
diff --git a/app/views/admin/domains/show.haml b/app/views/admin/domains/show.haml
index bbb790737..215ade8b1 100644
--- a/app/views/admin/domains/show.haml
+++ b/app/views/admin/domains/show.haml
@@ -24,4 +24,5 @@
.row
.col-md-12= render 'admin/domains/partials/keyrelays'
.row
- .col-md-12= render 'admin/domains/partials/legal_documents'
+ .col-md-12
+ = render 'admin/domains/partials/legal_documents', legal_documents: @domain.legal_documents
diff --git a/app/views/epp/contacts/_postal_info.xml.builder b/app/views/epp/contacts/_postal_info.xml.builder
index f9c6c5ee9..f84f177c9 100644
--- a/app/views/epp/contacts/_postal_info.xml.builder
+++ b/app/views/epp/contacts/_postal_info.xml.builder
@@ -1,13 +1,13 @@
-address = @contact.address
xml.tag!('contact:postalInfo', type: 'int') do
- xml.tag!('contact:name', @contact.name) if @disclosure.try(:[], :name) || @owner
- xml.tag!('contact:org', @contact.org_name) if @disclosure.try(:[], :org_name) || @owner
- if @disclosure.try(:addr) || @owner
+ xml.tag!('contact:name', @contact.name) #if @disclosure.try(:[], :name) || @owner
+ xml.tag!('contact:org', @contact.org_name) #if @disclosure.try(:[], :org_name) || @owner
+ # if @disclosure.try(:addr) || @owner
xml.tag!('contact:addr') do
- xml.tag!('contact:street', address.street) if address
- xml.tag!('contact:cc', address.country_code) unless address.country_code.nil?
- xml.tag!('contact:city', address.city) if address
+ xml.tag!('contact:street', @contact.street)
+ xml.tag!('contact:city', @contact.city)
+ xml.tag!('contact:pc', @contact.zip)
+ xml.tag!('contact:sp', @contact.state)
+ xml.tag!('contact:cc', @contact.country_code)
end
- end
+ # end
end
-
diff --git a/app/views/epp/contacts/check.xml.builder b/app/views/epp/contacts/check.xml.builder
index dab344196..4df3597e3 100644
--- a/app/views/epp/contacts/check.xml.builder
+++ b/app/views/epp/contacts/check.xml.builder
@@ -6,11 +6,10 @@ xml.epp_head do
xml.resData do
xml.tag!('contact:chkData', 'xmlns:contact' => 'urn:ietf:params:xml:ns:contact-1.0') do
- #xml.tag!('contact:id', @contact.code)
- @contacts.each do |contact|
+ @results.each do |result|
xml.tag!('contact:cd') do
- xml.tag! "contact:id", contact[:code], avail: contact[:avail]
- xml.tag!('contact:reason', contact[:reason]) unless contact[:avail] == 1
+ xml.tag! "contact:id", result[:code], avail: result[:avail]
+ xml.tag!('contact:reason', result[:reason]) unless result[:avail] == 1
end
end
end
diff --git a/app/views/epp/contacts/info.xml.builder b/app/views/epp/contacts/info.xml.builder
index 0f4560041..24480062d 100644
--- a/app/views/epp/contacts/info.xml.builder
+++ b/app/views/epp/contacts/info.xml.builder
@@ -8,9 +8,9 @@ xml.epp_head do
xml.tag!('contact:chkData', 'xmlns:contact' => 'urn:ietf:params:xml:ns:contact-1.0') do
xml.tag!('contact:id', @contact.code)
xml << render('/epp/contacts/postal_info')
- xml.tag!('contact:voice', @contact.phone) if @disclosure.try(:phone) || @owner
- xml.tag!('contact:fax', @contact.fax) if @disclosure.try(:fax) || @owner
- xml.tag!('contact:email', @contact.email) if @disclosure.try(:email) || @owner
+ xml.tag!('contact:voice', @contact.phone) #if @disclosure.try(:phone) || @owner
+ xml.tag!('contact:fax', @contact.fax) #if @disclosure.try(:fax) || @owner
+ xml.tag!('contact:email', @contact.email) #if @disclosure.try(:email) || @owner
xml.tag!('contact:clID', @contact.registrar.try(:name))
xml.tag!('contact:crID', @contact.creator.try(:registrar))
xml.tag!('contact:crDate', @contact.created_at)
@@ -18,18 +18,17 @@ xml.epp_head do
xml.tag!('contact:upID', @contact.updator.try(:registrar))
xml.tag!('contact:upDate', @contact.updated_at)
end
- xml.tag!('contact:ident', @contact.ident, type: @contact.ident_type)
- xml.tag!('contact:trDate', '123') if false
- if @owner
+ xml.tag!('contact:ident', @contact.ident, type: @contact.ident_type, cc: @contact.ident_country_code)
+ # xml.tag!('contact:trDate', '123') if false
+ if can? :view_password, @contact
xml.tag!('contact:authInfo') do
- xml.tag!('contact:pw', @contact.auth_info) # Doc says we have to return this but is it necessary?
+ xml.tag!('contact:pw', @contact.auth_info)
end
end
- # statuses
- @contact.statuses.each do |cs|
- xml.tag!('contact:status', s: cs.value)
+ @contact.statuses.each do |status|
+ xml.tag!('contact:status', s: status.value)
end
- xml << render('/epp/contacts/disclosure_policy')
+ # xml << render('/epp/contacts/disclosure_policy')
end
end
diff --git a/app/views/layouts/application.haml b/app/views/layouts/application.haml
index 05e513372..13ab2aab7 100644
--- a/app/views/layouts/application.haml
+++ b/app/views/layouts/application.haml
@@ -21,7 +21,7 @@
%span.icon-bar
%span.icon-bar
= link_to admin_dashboard_path, class: 'navbar-brand' do
- = APP_CONFIG['app_name']
+ = ENV['app_name']
- if unstable_env.present?
.text-center
%small{style: 'color: #0074B3;'}= unstable_env
diff --git a/bin/docker-robot b/bin/docker-robot
deleted file mode 100755
index fe41bd1f1..000000000
--- a/bin/docker-robot
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-#
-# For docker
-#
-
-# cd to Rails root directory
-cd "$(dirname "$0")"; cd ..
-
-bin/update-repo
-bin/robot
diff --git a/bin/robot b/bin/robot
index 28fbde348..9134a9137 100755
--- a/bin/robot
+++ b/bin/robot
@@ -16,14 +16,14 @@ export RAILS_ENV=test
cd "$(dirname "$0")"; cd ..
cp config/application-example.yml config/application.yml
-# create manually config/database.yml
+cp config/secrets-example.yml config/secrets.yml
+cp config/database-robot.yml config/database.yml
+# under jenkins use rbenv-plugin wrapper
bundle install
-RAILS_ENV=test bundle exec rake db:drop
-RAILS_ENV=test bundle exec rake db:all:create
-RAILS_ENV=test bundle exec rake db:all:schema:load
-RAILS_ENV=test bundle exec rake db:seed
+RAILS_ENV=test bundle exec rake db:all:drop
+RAILS_ENV=test bundle exec rake db:all:setup
RAILS_ENV=test bundle exec rake assets:precompile
echo "GIT_LAST_COMMITS"
@@ -36,6 +36,10 @@ RCODE=$?
echo "END_OF_RUBOCOP_RESULTS"
echo "TEST_RESULTS"
+# basic test
+# ROBOT=true bundle exec rake
+
+# all tests with EPP
ROBOT=true bundle exec rake test
TCODE=$?
echo "END_OF_TEST_RESULTS"
@@ -45,7 +49,7 @@ bundle exec bundle-audit update
bundle exec bundle-audit
BCODE=$?
BCODE=0 # tmp
-bundle exec brakeman
+bundle exec brakeman -q
echo "END_OF_SECURITY_RESULTS"
# update code review
diff --git a/config/application-example.yml b/config/application-example.yml
index 51a4661e5..31e5771fc 100644
--- a/config/application-example.yml
+++ b/config/application-example.yml
@@ -1,27 +1,29 @@
-defaults: &defaults
- app_name: .EE Registry
- zonefile_export_dir: 'export/zonefiles'
+# Be sure to restart your server when you modify settings.
- # You can use `rake secret` to generate a secure secret key.
- # Your secret key is used for verifying the integrity of signed cookies.
- # If you change this key, all old signed cookies will become invalid!
- secret_key_base: please-change-it-you-can-generate-it-with-rake-secret
- devise_secret: please-change-it-you-can-generate-it-with-rake-secret
- ca_cert_path: ca-cert-path-here
- ca_key_path: ca-key-path-here
- ca_key_password: ca-key-pass-phrase-here
+app_name: .EE Registry
+zonefile_export_dir: 'export/zonefiles'
-development:
- <<: *defaults
+# You can use `rake secret` to generate a secure secret key.
+# Your secret key is used for verifying the integrity of signed cookies.
+# If you change this key, all old signed cookies will become invalid!
+secret_key_base: please-change-it-you-can-generate-it-with-rake-secret
+devise_secret: please-change-it-you-can-generate-it-with-rake-secret
+# Used by admin server, you can leave those empty for when running EPP server:
+openssl_config_path: '/etc/ssl/openssl.cnf'
+crl_path: '/home/registry/registry/shared/ca/crl/crl.pem'
+ca_cert_path: '/home/registry/registry/shared/ca/certs/ca.crt.pem'
+ca_key_path: '/home/registry/registry/shared/ca/private/ca.key.pem'
+ca_key_password: 'your-root-key-password'
+
+# Used only by EPP server, you can leave it empty when running admin server:
+webclient_ip: '127.0.0.1'
+
+# autotest config overwrites
test:
- <<: *defaults
+ webclient_ip: '127.0.0.1' # it should match to localhost ip address
+ crl_path: '/var/lib/jenkins/workspace/registry/ca/crl/crl.pem'
+ ca_cert_path: '/var/lib/jenkins/workspace/registry/ca/certs/ca.crt.pem'
+ ca_key_path: '/var/lib/jenkins/workspace/registry/ca/private/ca.key.pem'
+ ca_key_password: 'test'
-alpha:
- <<: *defaults
-
-staging:
- <<: *defaults
-
-production:
- <<: *defaults
diff --git a/config/database-robot.yml b/config/database-robot.yml
new file mode 100644
index 000000000..b38a048a2
--- /dev/null
+++ b/config/database-robot.yml
@@ -0,0 +1,19 @@
+default: &default
+ host: localhost
+ adapter: postgresql
+ encoding: unicode
+ pool: 5
+ username: test
+ password: test
+
+test:
+ <<: *default
+ database: registry_test
+
+whois_test:
+ <<: *default
+ database: registry_whois_test
+
+api_log_test:
+ <<: *default
+ database: registry_api_log_test
diff --git a/config/database-travis.yml b/config/database-travis.yml
new file mode 100644
index 000000000..bf0765265
--- /dev/null
+++ b/config/database-travis.yml
@@ -0,0 +1,19 @@
+default: &default
+ host: localhost
+ adapter: postgresql
+ encoding: unicode
+ pool: 5
+ username: postgres
+ password:
+
+test:
+ <<: *default
+ database: registry_test
+
+whois_test:
+ <<: *default
+ database: registry_whois_test
+
+api_log_test:
+ <<: *default
+ database: registry_api_log_test
diff --git a/config/initializers/app_config.rb b/config/initializers/app_config.rb
deleted file mode 100644
index d76066b1a..000000000
--- a/config/initializers/app_config.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-APP_CONFIG = YAML.load_file("#{Rails.root}/config/application.yml")[Rails.env]
-Registry::Application.config.secret_token = APP_CONFIG['secret_key_base']
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index 8bbe137e2..6415ada3d 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -4,7 +4,7 @@ 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 = APP_CONFIG['devise_secret']
+ config.secret_key = ENV['devise_secret']
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
diff --git a/config/initializers/env_required.rb b/config/initializers/env_required.rb
new file mode 100644
index 000000000..c79520166
--- /dev/null
+++ b/config/initializers/env_required.rb
@@ -0,0 +1,13 @@
+required = %w(
+ app_name
+ zonefile_export_dir
+ secret_key_base
+ devise_secret
+ crl_path
+ ca_cert_path
+ ca_key_path
+ ca_key_password
+ webclient_ip
+)
+
+Figaro.require_keys(required)
diff --git a/config/initializers/initial_settings.rb b/config/initializers/initial_settings.rb
index 97743775f..5458b6d2e 100644
--- a/config/initializers/initial_settings.rb
+++ b/config/initializers/initial_settings.rb
@@ -1,4 +1,5 @@
-if ActiveRecord::Base.connection.table_exists? 'settings' # otherwise rake not working 100%
+# otherwise rake not working 100%
+if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.table_exists?('settings')
Setting.disclosure_name = true if Setting.disclosure_name.nil?
Setting.disclosure_name = true if Setting.disclosure_name.nil?
Setting.disclosure_org_name = true if Setting.disclosure_org_name.nil?
diff --git a/config/initializers/set_secret.rb b/config/initializers/set_secret.rb
new file mode 100644
index 000000000..ed1dbae7f
--- /dev/null
+++ b/config/initializers/set_secret.rb
@@ -0,0 +1 @@
+Registry::Application.config.secret_token = ENV['secret_key_base']
diff --git a/config/locales/en.yml b/config/locales/en.yml
index fc4ffbf3b..b2104e32c 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1,24 +1,3 @@
-# Files in the config/locales directory are used for internationalization
-# and are automatically loaded by Rails. If you want to use locales other
-# than English, add the necessary files in this directory.
-#
-# To use the locales, use `I18n.t`:
-#
-# I18n.t 'hello'
-#
-# In views, this is aliased to just `t`:
-#
-# <%= t('hello') %>
-#
-# To use a different locale, set it with `I18n.locale`:
-#
-# I18n.locale = :es
-#
-# This would use the information in config/locales/es.yml.
-#
-# To learn more, please read the Rails Internationalization guide
-# available at http://guides.rubyonrails.org/i18n.html.
-
en:
views:
pagination:
@@ -52,7 +31,6 @@ en:
activerecord:
errors:
models:
-
contact:
attributes:
code:
@@ -67,6 +45,8 @@ en:
invalid: "Email is invalid"
ident:
blank: "Required parameter missing - ident"
+ invalid_EE_identity_format: "Ident not in valid Estonian identity format."
+ invalid_birthday_format: "Ident not in valid birthady format, should be YYYY-MM-DD"
domains:
exist: 'Object association prohibits operation'
@@ -258,7 +238,7 @@ en:
invalid_type: 'PostalInfo type is invalid'
unimplemented_command: 'Unimplemented command'
domain_exists_but_belongs_to_other_registrar: 'Domain exists but belongs to other registrar'
-
+ required_attribute_missing: Required attributes missing
code: 'Code'
value: 'Value'
@@ -321,7 +301,7 @@ en:
domain_status_prohibits_deleting: 'Domain status prohibits deleting'
domain_deleted: 'Domain deleted!'
failed_to_delete_domain: 'Failed to delete domain!'
- email: 'Email'
+ email: 'E-mail'
fax: 'Fax'
contact_details: 'Contact details'
ident: 'Ident'
@@ -330,8 +310,8 @@ en:
country: 'Country'
city: 'City'
street: 'Street'
- zip: 'Zip'
- org_name: 'Organisation name'
+ zip: 'Postcode'
+ org_name: 'Org name'
failed_to_add_domain: 'Failed to add domain!'
domain_added: 'Domain added!'
new_contact: 'New contact'
@@ -502,3 +482,11 @@ en:
download: 'Download'
failed_to_create_certificate: 'Failed to create certificate!'
registrant_not_found: 'Registrant not found'
+ failed_to_revoke_certificate: 'Failed to revoke certificate!'
+ contact_code: Contact code
+ upload_csr: 'Upload CSR'
+ signature_algorithm: 'Signature algorithm'
+ version: 'Version'
+ sign_this_request: 'Sign this request'
+ revoke_this_certificate: 'Revoke this certificate'
+ crt_revoked: 'CRT (revoked)'
diff --git a/config/routes.rb b/config/routes.rb
index cd9f85b81..225ecaca2 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -3,6 +3,7 @@ require 'epp_constraint'
Rails.application.routes.draw do
namespace(:epp, defaults: { format: :xml }) do
match 'session/:action', controller: 'sessions', via: :all
+ match 'session/pki/:action', controller: 'sessions', via: :all
post 'command/:action', controller: 'domains', constraints: EppConstraint.new(:domain)
post 'command/:action', controller: 'contacts', constraints: EppConstraint.new(:contact)
@@ -47,9 +48,13 @@ Rails.application.routes.draw do
resources :admin_users
resources :api_users do
- member do
- get 'download_csr'
- get 'download_crt'
+ resources :certificates do
+ member do
+ post 'sign'
+ post 'revoke'
+ get 'download_csr'
+ get 'download_crt'
+ end
end
end
diff --git a/db/migrate/20150212125339_add_state_to_address.rb b/db/migrate/20150212125339_add_state_to_address.rb
new file mode 100644
index 000000000..a57412ce6
--- /dev/null
+++ b/db/migrate/20150212125339_add_state_to_address.rb
@@ -0,0 +1,5 @@
+class AddStateToAddress < ActiveRecord::Migration
+ def change
+ add_column :addresses, :state, :string
+ end
+end
diff --git a/db/migrate/20150217133755_add_country_code_ident.rb b/db/migrate/20150217133755_add_country_code_ident.rb
new file mode 100644
index 000000000..a45abd2aa
--- /dev/null
+++ b/db/migrate/20150217133755_add_country_code_ident.rb
@@ -0,0 +1,5 @@
+class AddCountryCodeIdent < ActiveRecord::Migration
+ def change
+ add_column :contacts, :ident_country_code, :string
+ end
+end
diff --git a/db/migrate/20150217133937_add_index_for_contact_code.rb b/db/migrate/20150217133937_add_index_for_contact_code.rb
new file mode 100644
index 000000000..ff5a4a94b
--- /dev/null
+++ b/db/migrate/20150217133937_add_index_for_contact_code.rb
@@ -0,0 +1,5 @@
+class AddIndexForContactCode < ActiveRecord::Migration
+ def change
+ add_index :contacts, :code
+ end
+end
diff --git a/db/migrate/20150223104842_create_certificates.rb b/db/migrate/20150223104842_create_certificates.rb
new file mode 100644
index 000000000..b84e9b5ce
--- /dev/null
+++ b/db/migrate/20150223104842_create_certificates.rb
@@ -0,0 +1,29 @@
+class CreateCertificates < ActiveRecord::Migration
+ def change
+ create_table :certificates do |t|
+ t.integer :api_user_id
+ t.text :csr
+ t.text :crt
+ t.string :creator_str
+ t.string :updator_str
+
+ t.timestamps
+ end
+
+ create_table :log_certificates do |t|
+ t.string "item_type", null: false
+ t.integer "item_id", null: false
+ t.string "event", null: false
+ t.string "whodunnit"
+ t.json "object"
+ t.json "object_changes"
+ t.datetime "created_at"
+ t.string "session"
+ t.json "children"
+ end
+
+ ApiUser.all.each do |x|
+ x.certificates << Certificate.new(crt: x.crt, csr: x.csr)
+ end
+ end
+end
diff --git a/db/migrate/20150227113121_change_api_user_default_value.rb b/db/migrate/20150227113121_change_api_user_default_value.rb
new file mode 100644
index 000000000..614abb587
--- /dev/null
+++ b/db/migrate/20150227113121_change_api_user_default_value.rb
@@ -0,0 +1,5 @@
+class ChangeApiUserDefaultValue < ActiveRecord::Migration
+ def change
+ change_column_default :users, :active, nil
+ end
+end
diff --git a/db/migrate/20150303130729_add_code_to_registrar.rb b/db/migrate/20150303130729_add_code_to_registrar.rb
new file mode 100644
index 000000000..6dea363fe
--- /dev/null
+++ b/db/migrate/20150303130729_add_code_to_registrar.rb
@@ -0,0 +1,6 @@
+class AddCodeToRegistrar < ActiveRecord::Migration
+ def change
+ add_column :registrars, :code, :string
+ add_index :registrars, :code
+ end
+end
diff --git a/db/migrate/20150303151224_data_update_regisntrar_codes.rb b/db/migrate/20150303151224_data_update_regisntrar_codes.rb
new file mode 100644
index 000000000..e49af65cb
--- /dev/null
+++ b/db/migrate/20150303151224_data_update_regisntrar_codes.rb
@@ -0,0 +1,11 @@
+class DataUpdateRegisntrarCodes < ActiveRecord::Migration
+ def change
+ puts 'Registrar code updates:'
+ Registrar.all.each do |r|
+ next if r.code.present?
+ r[:code] = r.name.parameterize
+ puts "#{r.id}: #{r.changes.inspect}"
+ r.save(validate: false)
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 614fe9ae6..fdedb6f22 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: 20150213104014) do
+ActiveRecord::Schema.define(version: 20150303151224) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -29,6 +29,7 @@ ActiveRecord::Schema.define(version: 20150213104014) do
t.string "creator_str"
t.string "updator_str"
t.string "country_code"
+ t.string "state"
end
create_table "api_users", force: :cascade do |t|
@@ -52,6 +53,16 @@ ActiveRecord::Schema.define(version: 20150213104014) do
add_index "cached_nameservers", ["hostname", "ipv4", "ipv6"], name: "index_cached_nameservers_on_hostname_and_ipv4_and_ipv6", unique: true, using: :btree
+ create_table "certificates", force: :cascade do |t|
+ t.integer "api_user_id"
+ t.text "csr"
+ t.text "crt"
+ t.string "creator_str"
+ t.string "updator_str"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
create_table "contact_disclosures", force: :cascade do |t|
t.integer "contact_id"
t.boolean "phone"
@@ -95,8 +106,11 @@ ActiveRecord::Schema.define(version: 20150213104014) do
t.integer "registrar_id"
t.string "creator_str"
t.string "updator_str"
+ t.string "ident_country_code"
end
+ add_index "contacts", ["code"], name: "index_contacts_on_code", using: :btree
+
create_table "countries", force: :cascade do |t|
t.string "iso"
t.string "name"
@@ -271,6 +285,18 @@ ActiveRecord::Schema.define(version: 20150213104014) do
add_index "log_api_users", ["item_type", "item_id"], name: "index_log_api_users_on_item_type_and_item_id", using: :btree
add_index "log_api_users", ["whodunnit"], name: "index_log_api_users_on_whodunnit", using: :btree
+ create_table "log_certificates", force: :cascade do |t|
+ t.string "item_type", null: false
+ t.integer "item_id", null: false
+ t.string "event", null: false
+ t.string "whodunnit"
+ t.json "object"
+ t.json "object_changes"
+ t.datetime "created_at"
+ t.string "session"
+ t.json "children"
+ end
+
create_table "log_contact_disclosures", force: :cascade do |t|
t.string "item_type", null: false
t.integer "item_id", null: false
@@ -585,8 +611,11 @@ ActiveRecord::Schema.define(version: 20150213104014) do
t.string "city"
t.string "street"
t.string "zip"
+ t.string "code"
end
+ add_index "registrars", ["code"], name: "index_registrars_on_code", using: :btree
+
create_table "reserved_domains", force: :cascade do |t|
t.string "name"
t.datetime "created_at"
@@ -614,19 +643,19 @@ ActiveRecord::Schema.define(version: 20150213104014) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "email"
- t.integer "sign_in_count", default: 0, null: false
+ t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.string "identity_code"
t.integer "country_id"
- t.string "roles", array: true
+ t.string "roles", array: true
t.string "creator_str"
t.string "updator_str"
t.string "country_code"
t.integer "registrar_id"
- t.boolean "active", default: false
+ t.boolean "active"
t.text "csr"
t.text "crt"
t.string "type"
diff --git a/db/seeds.rb b/db/seeds.rb
index ec49d6dbd..975dfa9b3 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -4,7 +4,10 @@
registrar1 = Registrar.where(
name: 'Registrar First AS',
reg_no: '10300220',
- address: 'Pärnu mnt 2, Tallinna linn, Harju maakond, 11415',
+ street: 'Pärnu mnt 2',
+ city: 'Tallinn',
+ state: 'Harju maakond',
+ zip: '11415',
email: 'registrar1@example.com',
country_code: 'EE'
).first_or_create!
@@ -19,7 +22,10 @@ ApiUser.where(
registrar2 = Registrar.where(
name: 'Registrar Second AS',
reg_no: '10529229',
- address: 'Vabaduse pst 32, 11316 Tallinn',
+ street: 'Vabaduse pst 32',
+ city: 'Tallinn',
+ state: 'Harju maakond',
+ zip: '11315',
email: 'registrar2@example.com',
country_code: 'EE'
).first_or_create!
@@ -55,4 +61,26 @@ AdminUser.where(
country_code: 'EE'
).first_or_create!
+ZonefileSetting.where({
+ origin: 'ee',
+ ttl: 43200,
+ refresh: 3600,
+ retry: 900,
+ expire: 1209600,
+ minimum_ttl: 3600,
+ email: 'hostmaster.eestiinternet.ee',
+ master_nameserver: 'ns.tld.ee'
+}).first_or_create!
+
+ZonefileSetting.where({
+ origin: 'pri.ee',
+ ttl: 43200,
+ refresh: 3600,
+ retry: 900,
+ expire: 1209600,
+ minimum_ttl: 3600,
+ email: 'hostmaster.eestiinternet.ee',
+ master_nameserver: 'ns.tld.ee'
+}).first_or_create!
+
AdminUser.update_all(roles: ['admin'])
diff --git a/doc/application_build_doc.md b/doc/application_build_doc.md
index bd817b08b..53c93415b 100644
--- a/doc/application_build_doc.md
+++ b/doc/application_build_doc.md
@@ -1,7 +1,48 @@
-### Application build and update
+Application build and update
+----------------------------
-For application deployment we are using faster [Mina](https://github.com/mina-deploy/mina)
-instead of Capistrano.
+### Debian setup
+
+* [Debian build](/doc/debian_build_doc.md)
+
+
+### Certificates setup
+
+* [Certificates setup](/doc/certificates.md)
+
+
+### Production env setup
+
+For production you probably would like to create databases to your locale, example:
+
+ create database registry_production owner registry encoding 'UTF-8' LC_COLLATE 'et_EE.utf8' LC_CTYPE 'et_EE.utf8' template template0;
+
+Deploy overview: (database schema should be loaded and seeds should be present)
+
+ # at your local machine
+ git clone git@github.com:internetee/registry.git
+ cd registry
+ rbenv local 2.2.0 # more info about rbenv at debian doc
+ gem install mina
+ mina pr setup # one time, only creates missing directories
+ ssh registry
+
+ # at your server
+ cd registry
+ cp current/config/application-example.yml shared/config/application.yml # and edit it
+ cp current/config/database-example.yml shared/config/database.yml # and edit it
+
+ vi /etc/apache2/sites-enabled/registry.conf # add conf and all needed serts
+ vi /etc/apache2/sites-enabled/epp.conf # add epp conf, restart apache
+ exit
+ # at your local machine
+ mina pr deploy # this is command you use in every application code update
+
+
+
+### Deploy script setup
+
+We recommend [Mina](https://github.com/mina-deploy/mina) instead of Capistrano for deployment.
All deploy code locates at config/deploy.rb file.
@@ -68,3 +109,13 @@ General rake and mina tips:
rake -T # list all rake commands
rake -T db # list all database related commands
mina -T # list all mina deploy commands
+
+
+CRON
+----
+
+Crontab can be setup after deploy. Jobs can be viewed [here](/config/schedule.rb).
+
+ mina pr cron:setup # to update the crontab.
+ mina pr cron:clear # to clear crontab.
+
diff --git a/doc/certificates.md b/doc/certificates.md
new file mode 100644
index 000000000..c8a304f9f
--- /dev/null
+++ b/doc/certificates.md
@@ -0,0 +1,196 @@
+Certificates setup
+------------------
+
+Guide to setup all registry/epp/repp, webclient and api user certificates.
+
+There are three type of certificates:
+
+* root cert (one time action using command line)
+* webclient server cert (one time action using command line)
+* api user cert (multiple actions through admin interface)
+
+API users CSR are uploaded through registry admin interface for each API user.
+
+Private key and certificate must be packaged to pkcs12 and added to user browser.
+
+
+### Registry setup
+
+Setup CA directory in shared directory:
+
+ cd /home/registry/registry/shared
+ mkdir ca ca/certs ca/crl ca/newcerts ca/private ca/csrs
+ cd ca
+ chmod 700 private
+ touch index.txt
+ echo 1000 > serial
+ echo 1000 > crlnumber
+
+Configure OpenSSL:
+
+ sudo cp /etc/ssl/openssl.cnf /etc/ssl/openssl.cnf.bak
+ sudo vi /etc/ssl/openssl.cnf
+
+Make sure the following options are in place:
+
+ [ CA_default ]
+ # Where everything is kept
+ dir = /home/registry/registry/shared/ca # around line nr 42
+
+ crl_extensions = crl_ext # around line nr 71
+
+ # For the CA policy
+ [ policy_match ]
+ countryName = optional # around line nr 85
+ stateOrProvinceName = optional # around line nr 86
+ organizationName = optional # around line nr 87
+ organizationalUnitName = optional # around line nr 88
+ commonName = supplied # around line nr 89
+ emailAddress = optional # around line nr 90
+
+ [ usr_cert ]
+ # These extensions are added when 'ca' signs a request.
+ basicConstraints=CA:FALSE # around line nr 170
+ keyUsage = nonRepudiation, digitalSignature, keyEncipherment # around line nr 188
+ nsComment = "OpenSSL Generated Certificate" # around line nr 191
+ subjectKeyIdentifier=hash # around line nr 194
+ authorityKeyIdentifier=keyid,issuer # around line nr 195
+
+ [ v3_ca ]
+ # Extensions for a typical CA
+ subjectKeyIdentifier=hash # around line nr 232
+ authorityKeyIdentifier=keyid:always,issuer # around line nr 234
+ basicConstraints = CA:true # around line nr 240
+ keyUsage = cRLSign, keyCertSign # around line nr 245
+
+Generate the root key and remember your password, you need it later in application.yml:
+
+ openssl genrsa -aes256 -out private/ca.key.pem 4096
+
+Create root registry certificate (prompts for additional data and review days flag):
+
+ openssl req -new -x509 -days 3653 -key private/ca.key.pem -sha256 -extensions v3_ca -out certs/ca.crt.pem
+ chmod 444 certs/ca.crt.pem
+
+Create a webclient key and CSR for accepting webclient request:
+
+ openssl genrsa -out private/webclient.key.pem 4096
+ chmod 400 private/webclient.key.pem
+ openssl req -sha256 -new -days 3653 -key private/webclient.key.pem -out csrs/webclient.csr.pem
+
+Sign CSR and create certificate:
+
+ openssl ca -keyfile private/ca.key.pem -cert certs/ca.crt.pem -extensions usr_cert -notext -md sha256 -in csrs/webclient.csr.pem -days 3653 -out certs/webclient.crt.pem
+ chmod 444 certs/webclient.crt.pem
+
+Create certificate revocation list (prompts for pass phrase):
+
+ openssl ca -keyfile private/ca.key.pem -cert certs/ca.crt.pem -gencrl -out crl/crl.pem
+
+Configure registry registry/shared/config/application.yml to match the CA settings:
+
+ openssl_config_path: '/etc/ssl/openssl.cnf'
+ crl_path: '/home/registry/registry/shared/ca/crl/crl.pem'
+ ca_cert_path: '/home/registry/registry/shared/ca/certs/ca.crt.pem'
+ ca_key_path: '/home/registry/registry/shared/ca/private/ca.key.pem'
+ ca_key_password: 'your-root-key-password'
+
+
+### Registry EPP setup
+
+Configure registry epp registry-epp/shared/config/application.yml:
+
+ webclient_ip: '54.154.91.240'
+
+Configure EPP port 700 virtual host:
+
+ sudo vi /etc/apache2/sites-enabled/epp.conf
+
+Replace this line:
+
+ SSLVerifyClient optional_no_ca
+
+With these lines:
+
+ SSLVerifyClient require
+ SSLVerifyDepth 1
+ SSLCACertificateFile /home/registry/registry/shared/ca/certs/ca.crt.pem
+ SSLCARevocationFile /home/registry/registry/shared/ca/crl/crl.pem
+ # Uncomment this when upgrading to apache 2.4:
+ # SSLCARevocationCheck chain
+ RequestHeader set SSL_CLIENT_S_DN_CN "%{SSL_CLIENT_S_DN_CN}s"
+
+Reload apache:
+
+ sudo a2enmod headers
+ sudo /etc/init.d/apache2 restart
+
+
+### Webclient setup
+
+Copy all registry/shared/ca directory to your webclient server if webclient is in different server,
+otherwise just point everything to your registry/shared/ca directory.
+
+Configure webclient/shared/config/application.yml to match the CA settings:
+
+ cert_path: '/home/webclient/webclient/shared/ca/certs/webclient.crt.pem'
+ key_path: '/home/webclient/webclient/shared/ca/private/webclient.key.pem'
+
+Configure webclient virtual host:
+
+ sudo vi /etc/apache2/sites-enabled/webclient.conf
+
+Add these lines:
+
+ SSLVerifyClient none
+ SSLVerifyDepth 1
+ SSLCACertificateFile /home/webclient/webclient/shared/ca/certs/ca.crt.pem
+ SSLCARevocationFile /home/webclient/webclient/shared/ca/crl/crl.pem
+ # Uncomment this when upgrading to apache 2.4:
+ # SSLCARevocationCheck chain
+
+ RequestHeader set SSL_CLIENT_S_DN_CN ""
+
+
+ SSLVerifyClient require
+ RequestHeader set SSL_CLIENT_S_DN_CN "%{SSL_CLIENT_S_DN_CN}s"
+
+
+Reload apache:
+
+ sudo a2enmod headers
+ sudo /etc/init.d/apache2 restart
+
+
+### ApiUser browser setup
+
+In short:
+
+* Upload CSR file to api user at admin page /admin/api_users
+* Sign it
+* Generate p12 file and install into user browser
+
+#### Creating CSR file
+
+ openssl genrsa -out private/api-user.key.pem 4096
+ chmod 400 private/api-user.key.pem
+ openssl req -sha256 -new -days 3653 -key private/api-user.key.pem -out csrs/api-user.csr.pem
+
+Upload api-user.csr.pem file to api user at admin interface.
+Sign it
+Download CRT file and create p12 file.
+
+ openssl pkcs12 -export -inkey private/api-user.key.pem -in certs/api-user.crt.pem -out pkcs/api_user.p12
+
+Add api_user.p12 to your browser.
+
+
+Development env
+---------------
+
+In development environment it's convenient to set unique_subject option to false,
+thus you can generate quickly as many certs as you wish.
+
+In CA directory:
+
+ echo "unique_subject = no" > index.txt.attr
diff --git a/doc/epp/contact.md b/doc/epp/contact.md
index 1117d0c86..db136c0db 100644
--- a/doc/epp/contact.md
+++ b/doc/epp/contact.md
@@ -1,6 +1,6 @@
## Contact related functions
-Please study official Cantact Mapping protocol:
+Please study official Contact Mapping protocol:
http://tools.ietf.org/html/rfc5733
More info at http://en.wikipedia.org/wiki/Extensible_Provisioning_Protocol
@@ -13,6 +13,7 @@ Contact Mapping protocol short version:
----------------------- ------- -----------------
1
1 Attribute: xmlns:contact="urn:ietf:params:xml:ns:contact-1.0"
+ 0-1 Contact id, optional, generated automatically if missing
1 Postal information container
1 Full name of the contact
0-1 Name of organization
@@ -30,12 +31,10 @@ Contact Mapping protocol short version:
"priv" # National idendtification number
"birthday" # Birthday date in format in DD-MM-YYYY
1
- 1 Attribute: xmlns:eis="urn:ee:eis:xml:epp:eis-1.0"
- 1 Base64 encoded document
+ 1 Attribute: xmlns:eis="urn:ee:eis:xml:epp:eis-1.0"
+ 1 Base64 encoded document
Attribute: type="pdf/bdoc/ddoc/zip/rar/gz/tar/7z"
-
-
[EXAMPLE REQUEST AND RESPONSE](/doc/epp-examples.md#epp-contact-with-valid-user-create-command-successfully-creates-a-contact)
### Contact update
@@ -44,7 +43,7 @@ Contact Mapping protocol short version:
----------------------- ------- -----------------
1
1 Attribute: xmlns:contact="urn:ietf:params:xml:ns:contact-1.0"
- 1 contact id, required
+ 1 Contact id, required
1 Change container
1 Postal information container
0-1 Full name of the contact
@@ -65,9 +64,9 @@ Contact Mapping protocol short version:
0-1 Required if registrar is not the owner of the contact.
1 Contact password. Attribute: roid="String"
0-1
- 0-1 Attribute: xmlns:eis="urn:ee:eis:xml:epp:eis-1.0"
- 0-1 Base64 encoded document.
- Attribute: type="pdf/bdoc/ddoc/zip/rar/gz/tar/7z"
+ 0-1 Attribute: xmlns:eis="urn:ee:eis:xml:epp:eis-1.0"
+ 0-1 Base64 encoded document.
+ Attribute: type="pdf/bdoc/ddoc/zip/rar/gz/tar/7z"
[EXAMPLE REQUEST AND RESPONSE](/doc/epp-examples.md#epp-contact-with-valid-user-update-command-is-succesful)
@@ -82,10 +81,10 @@ Contact Mapping protocol short version:
0-1 Required if registrar is not the owner of the contact.
1 Contact password. Attribute: roid="String"
1
- 1 Attribute: xmlns:eis="urn:ee:eis:xml:epp:eis-1.0"
- 1 Base64 encoded document.
+ 1 Attribute: xmlns:eis="urn:ee:eis:xml:epp:eis-1.0"
+ 1 Base64 encoded document.
Attribute: type="pdf/bdoc/ddoc/zip/rar/gz/tar/7z"
- 0-1 Client transaction id
+ 0-1 Client transaction id
[EXAMPLE REQUEST AND RESPONSE](/doc/epp-examples.md#epp-contact-with-valid-user-delete-command-deletes-contact)
diff --git a/doc/testing.md b/doc/testing.md
new file mode 100644
index 000000000..e7b56e0cb
--- /dev/null
+++ b/doc/testing.md
@@ -0,0 +1,114 @@
+Testing
+-------
+
+Setup test databases:
+
+ RAILS_ENV=test rake db:all:setup
+
+Run basic test (no EPP tests):
+
+ rake
+
+
+Testing EPP
+===========
+
+In order to test EPP, you have to configure apache to handle EPP request correctly.
+
+### Apache site config
+
+First you should have mod_epp installed, please follow main README for doing it.
+
+Apache site config for autotest, add file to /etc/apache2/sites-enabled/epp-autotest.conf
+
+```apache
+
+ Listen 701
+
+ SSLEngine on
+ SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
+ SSLCertificateFile /etc/apache2/ssl/apache.crt
+ SSLCertificateKeyFile /etc/apache2/ssl/apache.key
+
+ SSLVerifyClient optional_no_ca
+
+ EPPEngine On
+ EPPCommandRoot /proxy/command
+ EPPSessionRoot /proxy/session
+ EPPErrorRoot /proxy/error
+ EPPRawFrame raw_frame
+
+ ProxyPass /proxy/ http://localhost:8989/epp/
+
+ EPPAuthURI implicit
+ EPPReturncodeHeader X-EPP-Returncode
+
+
+```
+
+
+
+* Run all tests with temp server running automatically on port 8989:
+
+ rake test
+
+
+Manual debugging
+================
+
+### Apache mod_epp manual debugging
+
+Debugging Apache mod_epp without Registry app.
+
+ sudo apt-get install apache2-dbg
+
+Includes htpasswd command to generate authentication files
+
+ sudo apt-get install apache2-utils
+
+For manual debugging purposes, standalone CGI scripts can be used:
+This needs a static greeting file, so you will have to make /var/www writable.
+
+```apache
+
+
+ Options ExecCGI
+ SetHandler cgi-script
+
+
+ Listen 1700
+
+
+ EPPEngine On
+ EPPCommandRoot /cgi-bin/epp/command
+ EPPSessionRoot /cgi-bin/epp/session
+ EPPErrorRoot /cgi-bin/epp/error
+
+ Alias /cgi-bin/epp/session/hello /var/www/html/epp/session-hello
+
+ Alias /cgi-bin/epp/session/login /usr/lib/cgi-bin/epp/session-login
+ Alias /cgi-bin/epp/session/logout /usr/lib/cgi-bin/epp/session-logout
+ Alias /cgi-bin/epp/error/schema /usr/lib/cgi-bin/epp/error-schema
+ Alias /cgi-bin/epp/command/create /usr/lib/cgi-bin/epp/create
+ Alias /cgi-bin/epp/command/info /usr/lib/cgi-bin/epp/info
+
+ EPPAuthURI /epp/auth/login
+
+ AuthType Basic
+ AuthName "EPP"
+ AuthUserFile /etc/apache2/htpasswd
+ require valid-user
+
+
+
+```
+
+ sudo a2enmod cgi
+ sudo a2enmod authn_file # will be used for non implicit authentication URIs
+ sudo htpasswd -c /etc/apache2/htpasswd test
+ Type "test" when prompted
+ cd /usr/lib/cgi-bin
+ mkdir epp
+
+Copy the files from $mod_epp/examples/cgis to /usr/lib/cgi-bin/epp
+
diff --git a/lib/tasks/db.rake b/lib/tasks/db.rake
index 3108ad02f..fd35f1f23 100644
--- a/lib/tasks/db.rake
+++ b/lib/tasks/db.rake
@@ -1,16 +1,14 @@
namespace :db do
- def databases
- @db ||= ["api_log_#{Rails.env}", "whois_#{Rails.env}", "#{Rails.env}"]
+ def other_databases
+ @db ||= ["api_log_#{Rails.env}", "whois_#{Rails.env}"]
end
def schema_file(db)
case db
- when databases.first
+ when "api_log_#{Rails.env}"
'api_log_schema.rb'
- when databases.second
+ when "whois_#{Rails.env}"
'whois_schema.rb'
- when databases.third
- 'schema.rb'
end
end
@@ -19,16 +17,51 @@ namespace :db do
task setup: [:environment] do
Rake::Task['db:all:create'].invoke
Rake::Task['db:all:schema:load'].invoke
- Rake::Task['db:seed'].invoke
+
+ ActiveRecord::Base.clear_all_connections!
+ ActiveRecord::Base.establish_connection(Rails.env.to_sym)
+ # puts "\n---------------------------- Import seed ----------------------------------------\n"
+ # Rake::Task['db:seed'].invoke
+ puts "\n All done!\n\n"
end
desc 'Create all databases: registry, api_log and whois'
task create: [:environment] do
- databases.each do |name|
+ puts "\n---------------------------- Create main database ----------------------------------------\n"
+ Rake::Task['db:create'].invoke
+
+ other_databases.each do |name|
begin
- conf = ActiveRecord::Base.configurations
+ puts "\n---------------------------- Create #{name} ----------------------------------------\n"
ActiveRecord::Base.clear_all_connections!
- ActiveRecord::Base.connection.create_database(conf[name]['database'], conf[name])
+ conf = ActiveRecord::Base.configurations
+ ActiveRecord::Base.connection.create_database(conf[name]['database'].to_sym, conf[name])
+ rescue => e
+ puts "\n#{e}"
+ end
+ end
+ end
+
+ desc 'Drop all databaseses: registry, api_log and whois'
+ task drop: [:environment] do
+ # just in case we allow only drop test, comment it out please for temp
+ return unless Rails.env.test?
+
+ Rake::Task['db:drop'].invoke
+ conf = ActiveRecord::Base.configurations
+ puts "#{conf[Rails.env]['database']} dropped"
+
+ other_databases.each do |name|
+ begin
+ ActiveRecord::Base.clear_all_connections!
+ ActiveRecord::Base.establish_connection(name.to_sym)
+
+ conf = ActiveRecord::Base.configurations
+ if ActiveRecord::Tasks::DatabaseTasks.drop(conf[name])
+ puts "#{conf[name]['database']} dropped"
+ else
+ puts "Didn't find database #{name}, no drop"
+ end
rescue => e
puts "\n#{e}"
end
@@ -38,10 +71,14 @@ namespace :db do
namespace :schema do
desc 'Schema load for all databases: registry, api_log and whois'
task load: [:environment] do
- databases.each do |name|
+ puts "\n---------------------------- Main schema load ----------------------------------------\n"
+ Rake::Task['db:schema:load'].invoke
+
+ other_databases.each do |name|
begin
- puts "\n---------------------------- #{name} ----------------------------------------\n"
- ActiveRecord::Base.establish_connection(name)
+ puts "\n---------------------------- #{name} schema loaded ----------------------------------------\n"
+ ActiveRecord::Base.clear_all_connections!
+ ActiveRecord::Base.establish_connection(name.to_sym)
if ActiveRecord::Base.connection.table_exists?('schema_migrations')
puts 'Found tables, skip schema load!'
else
@@ -55,7 +92,10 @@ namespace :db do
desc 'Schema load for all databases: registry, api_log and whois'
task dump: [:environment] do
- databases.each do |name|
+ puts "\n---------------------------- Main schema load ----------------------------------------\n"
+ Rake::Task['db:schema:dump'].invoke
+
+ other_databases.each do |name|
begin
puts "\n---------------------------- #{name} ----------------------------------------\n"
filename = "#{Rails.root}/db/#{schema_file(name)}"
diff --git a/lib/tasks/test.rake b/lib/tasks/test.rake
index 20e3f5f91..ac5b5159d 100644
--- a/lib/tasks/test.rake
+++ b/lib/tasks/test.rake
@@ -30,7 +30,7 @@ begin
end
Rake::Task[:default].prerequisites.clear
- task default: :test
+ task default: 'test:other'
def test_against_server
_stdin, _stdout, _stderr, wait_thr = Open3.popen3('unicorn -E test -p 8989')
diff --git a/spec/epp/contact_spec.rb b/spec/epp/contact_spec.rb
index 62de51c5a..4690acfed 100644
--- a/spec/epp/contact_spec.rb
+++ b/spec/epp/contact_spec.rb
@@ -1,451 +1,441 @@
-# require 'rails_helper'
-
-# describe 'EPP Contact', epp: true do
-# before :all do
-# create_settings
-# create_disclosure_settings
-# @registrar1 = Fabricate(:registrar1)
-# @registrar2 = Fabricate(:registrar2)
-# @epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345')
-
-# Fabricate(:api_user, username: 'registrar1', registrar: @registrar1)
-# Fabricate(:api_user, username: 'registrar2', registrar: @registrar2)
-
-# login_as :registrar1
-
-# Contact.skip_callback(:create, :before, :generate_code)
-# Contact.skip_callback(:create, :before, :generate_auth_info)
-# end
-
-# after :all do
-# Contact.set_callback(:create, :before, :generate_code)
-# Contact.set_callback(:create, :before, :generate_auth_info)
-# end
-
-# context 'with valid user' do
-# context 'create command' do
-# it 'fails if request xml is missing' do
-# xml = @epp_xml.create
-# response = epp_plain_request(xml, :xml)
-# response[:results][0][:msg].should == 'Command syntax error'
-# response[:results][0][:result_code].should == '2001'
-
-# response[:results].count.should == 1
-# end
-
-# it 'fails if request xml is missing' do
-# xml = @epp_xml.create(
-# postalInfo: { addr: { value: nil } }
-# )
-# response = epp_plain_request(xml, :xml)
-# response[:results][0][:msg].should == 'Required parameter missing: name'
-# response[:results][1][:msg].should == 'Required parameter missing: city'
-# response[:results][2][:msg].should == 'Required parameter missing: cc'
-# response[:results][3][:msg].should == 'Required parameter missing: ident'
-# response[:results][4][:msg].should == 'Required parameter missing: voice'
-# response[:results][5][:msg].should == 'Required parameter missing: email'
-
-# response[:results][0][:result_code].should == '2003'
-# response[:results][1][:result_code].should == '2003'
-# response[:results][2][:result_code].should == '2003'
-# response[:results][3][:result_code].should == '2003'
-# response[:results][4][:result_code].should == '2003'
-# response[:results][5][:result_code].should == '2003'
-
-# response[:results].count.should == 6
-# end
-
-# it 'successfully saves ident type' do
-# xml = { ident: { value: '1990-22-12', attrs: { type: 'birthday' } } }
-# epp_plain_request(create_contact_xml(xml), :xml)
-
-# Contact.last.ident_type.should == 'birthday'
-# end
-
-# it 'successfully creates a contact' do
-# response = epp_plain_request(create_contact_xml, :xml)
-
-# response[:msg].should == 'Command completed successfully'
-# response[:result_code].should == '1000'
-
-# @contact = Contact.last
-
-# @contact.registrar.should == @registrar1
-# # registrar1.api_users.should include(@contact.created_by)
-# # @contact.updated_by_id.should == nil
-# @contact.ident.should == '37605030299'
-# @contact.address.street.should == '123 Example'
-
-# log = ApiLog::EppLog.last
-# log.request_command.should == 'create'
-# log.request_object.should == 'contact'
-# log.request_successful.should == true
-# log.api_user_name.should == '1-api-registrar1'
-# log.api_user_registrar.should == 'registrar1'
-# end
-
-# it 'successfully adds registrar' do
-# response = epp_plain_request(create_contact_xml, :xml)
-
-# response[:msg].should == 'Command completed successfully'
-# response[:result_code].should == '1000'
-
-# Contact.last.registrar.should == @registrar1
-# end
-
-# it 'returns result data upon success' do
-# response = epp_plain_request(create_contact_xml, :xml)
-
-# response[:msg].should == 'Command completed successfully'
-# response[:result_code].should == '1000'
-
-# id = response[:parsed].css('resData creData id').first
-# cr_date = response[:parsed].css('resData creData crDate').first
-
-# id.text.length.should == 8
-# # 5 seconds for what-ever weird lag reasons might happen
-# cr_date.text.to_time.should be_within(5).of(Time.now)
-# end
-
-# it 'creates disclosure data' do
-# xml = {
-# disclose: { value: {
-# voice: { value: '' },
-# addr: { value: '' },
-# name: { value: '' },
-# org_name: { value: '' },
-# email: { value: '' },
-# fax: { value: '' }
-# }, attrs: { flag: '1' }
-# }
-# }
-
-# response = epp_plain_request(create_contact_xml(xml), :xml)
-# response[:result_code].should == '1000'
-
-# @contact = Contact.last
-# @contact.disclosure.name.should == true
-# @contact.disclosure.org_name.should == true
-# @contact.disclosure.phone.should == true
-# @contact.disclosure.fax.should == true
-# @contact.disclosure.email.should == true
-# @contact.disclosure.address.should == true
-# end
-
-# it 'creates disclosure data merging with defaults' do
-# xml = {
-# disclose: { value: {
-# voice: { value: '' },
-# addr: { value: '' }
-# }, attrs: { flag: '1' }
-# }
-# }
-
-# response = epp_plain_request(create_contact_xml(xml), :xml)
-# response[:result_code].should == '1000'
-
-# @contact = Contact.last
-# @contact.disclosure.name.should == nil
-# @contact.disclosure.org_name.should == nil
-# @contact.disclosure.phone.should == true
-# @contact.disclosure.fax.should == nil
-# @contact.disclosure.email.should == nil
-# @contact.disclosure.address.should == true
-# end
-# end
-
-# context 'update command' do
-# before :all do
-# @contact =
-# Fabricate(
-# :contact,
-# # created_by_id: 1,
-# registrar: @registrar1,
-# email: 'not_updated@test.test',
-# code: 'sh8013',
-# auth_info: 'password'
-# )
-# end
-
-# it 'fails if request is invalid' do
-# xml = @epp_xml.update
-# response = epp_plain_request(xml, :xml) # epp_request('contacts/update_missing_attr.xml')
-
-# response[:results][0][:result_code].should == '2003'
-# response[:results][0][:msg].should == 'Required parameter missing: add, rem or chg'
-# response[:results][1][:result_code].should == '2003'
-# response[:results][1][:msg].should == 'Required parameter missing: id'
-# response[:results].count.should == 2
-# end
-
-# it 'fails with wrong authentication info' do
-# login_as :registrar2 do
-# response = epp_plain_request(update_contact_xml({ id: { value: 'sh8013' } }), :xml)
-# expect(response[:msg]).to eq('Authorization error')
-# expect(response[:result_code]).to eq('2201')
-# end
-# end
-
-# it 'is succesful' do
-# response = epp_plain_request(update_contact_xml({ id: { value: 'sh8013' } }), :xml)
-
-# response[:msg].should == 'Command completed successfully'
-# @contact.reload
-# @contact.name.should == 'John Doe Edited'
-# @contact.email.should == 'edited@example.example'
-# end
-
-# it 'returns phone and email error' do
-# xml = {
-# id: { value: 'sh8013' },
-# chg: {
-# voice: { value: '123213' },
-# email: { value: 'aaa' }
-# }
-# }
-
-# response = epp_plain_request(update_contact_xml(xml), :xml)
-
-# response[:results][0][:msg].should == 'Phone nr is invalid'
-# response[:results][0][:result_code].should == '2005'
-
-# response[:results][1][:msg].should == 'Email is invalid'
-# response[:results][1][:result_code].should == '2005'
-# end
-
-# it 'updates disclosure items' do
-# Fabricate(
-# :contact,
-# code: 'sh8013disclosure',
-# auth_info: '2fooBAR',
-# registrar: @registrar1,
-# # created_by_id: ApiUser.first.id,
-# disclosure: Fabricate(:contact_disclosure, phone: true, email: true))
-
-# xml = {
-# id: { value: 'sh8013disclosure' },
-# authInfo: { pw: { value: '2fooBAR' } }
-# }
-# @response = epp_plain_request(update_contact_xml(xml), :xml)
-
-# @response[:results][0][:msg].should == 'Command completed successfully'
-# @response[:results][0][:result_code].should == '1000'
-
-# Contact.last.disclosure.phone.should == false
-# Contact.last.disclosure.email.should == false
-# end
-# end
-
-# context 'delete command' do
-# it 'fails if request is invalid' do
-# xml = @epp_xml.delete({ uid: { value: '23123' } })
-# response = epp_plain_request(xml, :xml)
-
-# response[:results][0][:msg].should == 'Required parameter missing: id'
-# response[:results][0][:result_code].should == '2003'
-# response[:results].count.should == 1
-# end
-
-# it 'deletes contact' do
-# @contact_deleted =
-# # Fabricate(:contact, code: 'dwa1234', created_by_id: ApiUser.first.id, registrar: registrar1)
-# Fabricate(:contact, code: 'dwa1234', registrar: @registrar1)
-
-# response = epp_plain_request(delete_contact_xml({ id: { value: 'dwa1234' } }), :xml)
-# response[:msg].should == 'Command completed successfully'
-# response[:result_code].should == '1000'
-# response[:clTRID].should == 'ABC-12345'
-
-# Contact.find_by_id(@contact_deleted.id).should == nil
-# end
-
-# it 'returns error if obj doesnt exist' do
-# response = epp_plain_request(delete_contact_xml, :xml)
-# response[:msg].should == 'Object does not exist'
-# response[:result_code].should == '2303'
-# end
-
-# it 'fails if contact has associated domain' do
-# Fabricate(
-# :domain,
-# registrar: @registrar1,
-# owner_contact: Fabricate(
-# :contact,
-# code: 'dwa1234',
-# # created_by_id: registrar1.id,
-# registrar: @registrar1)
-# )
-# Domain.last.owner_contact.address.present?.should == true
-# response = epp_plain_request(delete_contact_xml({ id: { value: 'dwa1234' } }), :xml)
-
-# response[:msg].should == 'Object association prohibits operation'
-# response[:result_code].should == '2305'
-
-# Domain.last.owner_contact.present?.should == true
-# end
-# end
-
-# context 'check command' do
-# it 'fails if request is invalid' do
-# xml = @epp_xml.check({ uid: { value: '123asde' } })
-# response = epp_plain_request(xml, :xml)
-
-# response[:results][0][:msg].should == 'Required parameter missing: id'
-# response[:results][0][:result_code].should == '2003'
-# response[:results].count.should == 1
-# end
-
-# it 'returns info about contact availability' do
-# Fabricate(:contact, code: 'check-1234')
-
-# response = epp_plain_request(check_multiple_contacts_xml, :xml)
-
-# response[:msg].should == 'Command completed successfully'
-# response[:result_code].should == '1000'
-# ids = response[:parsed].css('resData chkData id')
-
-# ids[0].attributes['avail'].text.should == '0'
-# ids[1].attributes['avail'].text.should == '1'
-
-# ids[0].text.should == 'check-1234'
-# ids[1].text.should == 'check-4321'
-# end
-# end
-
-# # context 'info command' do
-# # before :all do
-# # @registrar1_contact = Fabricate(:contact, code: 'info-4444', registrar: @registrar1,
-# # name: 'Johnny Awesome', address: Fabricate(:address))
-# # end
-
-# # fit 'return info about contact' do
-# # login_as :registrar2 do
-# # xml = @epp_xml.info(id: { value: @registrar1_contact.code })
-# # response = epp_plain_request(xml, :xml)
-# # response[:msg].should == 'Command completed successfully'
-# # response[:result_code].should == '1000'
-
-# # contact = response[:parsed].css('resData chkData')
-# # contact.css('name').first.text.should == 'Johnny Awesome'
-# # end
-# # end
-
-# # it 'fails if request invalid' do
-# # response = epp_plain_request(@epp_xml.info({ wrongid: { value: '123123' } }), :xml)
-# # response[:results][0][:msg].should == 'Required parameter missing: id'
-# # response[:results][0][:result_code].should == '2003'
-# # response[:results].count.should == 1
-# # end
-
-# # it 'returns error when object does not exist' do
-# # response = epp_plain_request(info_contact_xml({ id: { value: 'no-contact' } }), :xml)
-# # response[:msg].should == 'Object does not exist'
-# # response[:result_code].should == '2303'
-# # response[:results][0][:value].should == 'no-contact'
-# # end
-
-# # # it 'returns auth error for non-owner with wrong password' do
-# # # @contact = Fabricate(:contact,
-# # # registrar: registrar2, code: 'info-4444', name: 'Johnny Awesome', auth_info: 'asde',
-# # # address: Fabricate(:address), disclosure: Fabricate(:contact_disclosure, name: false))
-
-# # # xml = @epp_xml.info({ id: { value: @contact.code }, authInfo: { pw: { value: 'asdesde' } } })
-# # # response = epp_plain_request(xml, :xml, :registrar1)
-
-# # # expect(response[:result_code]).to eq('2200')
-# # # expect(response[:msg]).to eq('Authentication error')
-# # # end
-
-# # context 'about disclose' do
-# # it 'discloses items with wrong password when queried by owner' do
-# # @contact = Fabricate(:contact,
-# # registrar: registrar1, code: 'info-4444',
-# # name: 'Johnny Awesome', auth_info: 'asde',
-# # address: Fabricate(:address), disclosure: Fabricate(:contact_disclosure, name: false))
-
-# # xml = @epp_xml.info({ id: { value: @contact.code } })
-# # login_as :registrar1 do
-# # response = epp_plain_request(xml, :xml)
-# # contact = response[:parsed].css('resData chkData')
-
-# # expect(response[:result_code]).to eq('1000')
-# # expect(response[:msg]).to eq('Command completed successfully')
-# # expect(contact.css('name').first.text).to eq('Johnny Awesome')
-# # end
-# # end
-
-# # it 'doesn\'t disclose items to non-owner with right password' do
-# # @contact = Fabricate(:contact, registrar: registrar2, code: 'info-4444',
-# # name: 'Johnny Awesome', auth_info: 'password',
-# # address: Fabricate(:address), disclosure: Fabricate(:contact_disclosure, name: false))
-
-# # xml = @epp_xml.info({ id: { value: @contact.code }, authInfo: { pw: { value: 'password' } } })
-# # response = epp_plain_request(xml, :xml, :registrar1)
-# # contact = response[:parsed].css('resData chkData')
-
-# # expect(response[:result_code]).to eq('1000')
-# # expect(response[:msg]).to eq('Command completed successfully')
-# # expect(contact.css('chkData postalInfo name').first).to eq(nil)
-# # end
-
-# # it 'discloses items to owner' do
-# # @contact = Fabricate(:contact, registrar: registrar1, code: 'info-4444', name: 'Johnny Awesome',
-# # auth_info: 'password',
-# # address: Fabricate(:address), disclosure: Fabricate(:contact_disclosure, name: false))
-
-# # xml = @epp_xml.info({ id: { value: @contact.code } })
-# # response = epp_plain_request(xml, :xml, :registrar1)
-# # contact = response[:parsed].css('resData chkData')
-
-# # expect(response[:result_code]).to eq('1000')
-# # expect(response[:msg]).to eq('Command completed successfully')
-# # expect(contact.css('name').first.text).to eq('Johnny Awesome')
-# # end
-
-# # it 'doesn\'t disclose private elements' do
-# # Fabricate(:contact, code: 'info-4444', auth_info: '2fooBAR', registrar: registrar2,
-# # disclosure: Fabricate(:contact_disclosure, name: true, email: false, phone: false))
-
-# # xml = @epp_xml.info({ id: { value: 'info-4444' }, authInfo: { pw: { value: '2fooBAR' } } })
-
-# # response = epp_plain_request(xml, :xml, :registrar1)
-# # contact = response[:parsed].css('resData chkData')
-
-# # expect(response[:result_code]).to eq('1000')
-
-# # expect(contact.css('chkData phone')).to eq(contact.css('chkData disclose phone'))
-# # expect(contact.css('chkData phone').count).to eq(1)
-# # expect(contact.css('chkData email')).to eq(contact.css('chkData disclose email'))
-# # expect(contact.css('chkData email').count).to eq(1)
-# # expect(contact.css('postalInfo name').present?).to be(true)
-# # end
-# # end
-
-# # it 'does not display unassociated object without password' do
-# # xml = @epp_xml.info(id: { value: @registrar1_contact.code })
-# # response = epp_plain_request(xml, :xml, :registrar2)
-# # expect(response[:result_code]).to eq('2003')
-# # expect(response[:msg]).to eq('Required parameter missing: pw')
-# # end
-
-# # it 'does not display unassociated object with wrong password' do
-# # login_as :registrar2
-# # xml = @epp_xml.info(id: { value: @registrar1_contact.code },
-# # authInfo: { pw: { value: 'wrong-pw' } })
-# # response = epp_plain_request(xml, :xml)
-
-# # response[:msg].should == 'Authentication error'
-# # response[:result_code].should == '2200'
-# # end
-# # end
-
-# context 'renew command' do
-# it 'returns 2101-unimplemented command' do
-# response = epp_plain_request('contacts/renew.xml')
-
-# response[:msg].should == 'Unimplemented command'
-# response[:result_code].should == '2101'
-# end
-# end
-# end
-# end
+require 'rails_helper'
+
+describe 'EPP Contact', epp: true do
+ before :all do
+ create_settings
+ create_disclosure_settings
+ @registrar1 = Fabricate(:registrar1)
+ @registrar2 = Fabricate(:registrar2)
+ @epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345')
+
+ Fabricate(:api_user, username: 'registrar1', registrar: @registrar1)
+ Fabricate(:api_user, username: 'registrar2', registrar: @registrar2)
+
+ login_as :registrar1
+
+ @contact = Fabricate(:contact, registrar: @registrar1)
+
+ @legal_document = {
+ legalDocument: {
+ value: 'JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0Zp==',
+ attrs: { type: 'pdf' }
+ }
+ }
+ end
+
+ context 'with valid user' do
+ context 'create command' do
+ def create_request(overwrites = {})
+ defaults = {
+ postalInfo: {
+ name: { value: 'John Doe' },
+ addr: {
+ street: { value: '123 Example' },
+ city: { value: 'Tallinn' },
+ cc: { value: 'EE' }
+ }
+ },
+ voice: { value: '+372.1234567' },
+ email: { value: 'test@example.example' },
+ ident: { value: '37605030299', attrs: { type: 'priv', cc: 'EE' } }
+ }
+ create_xml = @epp_xml.create(defaults.deep_merge(overwrites), @legal_document)
+ epp_plain_request(create_xml, :xml)
+ end
+
+ it 'fails if request xml is missing' do
+ response = epp_plain_request(@epp_xml.create, :xml)
+ response[:results][0][:msg].should ==
+ 'Required parameter missing: create > create > postalInfo > name [name]'
+ response[:results][1][:msg].should ==
+ 'Required parameter missing: create > create > postalInfo > addr > city [city]'
+ response[:results][2][:msg].should ==
+ 'Required parameter missing: create > create > postalInfo > addr > cc [cc]'
+ response[:results][3][:msg].should ==
+ 'Required parameter missing: create > create > ident [ident]'
+ response[:results][4][:msg].should ==
+ 'Required parameter missing: create > create > voice [voice]'
+ response[:results][5][:msg].should ==
+ 'Required parameter missing: create > create > email [email]'
+ response[:results][6][:msg].should ==
+ 'Required parameter missing: extension > extdata > legalDocument [legal_document]'
+
+ response[:results][0][:result_code].should == '2003'
+ response[:results][1][:result_code].should == '2003'
+ response[:results][2][:result_code].should == '2003'
+ response[:results][3][:result_code].should == '2003'
+ response[:results][4][:result_code].should == '2003'
+ response[:results][5][:result_code].should == '2003'
+ response[:results][6][:result_code].should == '2003'
+
+ response[:results].count.should == 7
+ end
+
+ it 'successfully creates a contact' do
+ response = create_request
+
+ response[:msg].should == 'Command completed successfully'
+ response[:result_code].should == '1000'
+
+ @contact = Contact.last
+
+ @contact.registrar.should == @registrar1
+ @registrar1.api_users.should include(@contact.creator)
+ @contact.ident.should == '37605030299'
+ @contact.address.street.should == '123 Example'
+ @contact.legal_documents.count.should == 1
+
+ log = ApiLog::EppLog.last
+ log.request_command.should == 'create'
+ log.request_object.should == 'contact'
+ log.request_successful.should == true
+ log.api_user_name.should == '1-api-registrar1'
+ log.api_user_registrar.should == 'registrar1'
+ end
+
+ it 'successfully saves ident type' do
+ response = create_request(
+ { ident: { value: '1990-22-12', attrs: { type: 'birthday' } } }
+ )
+
+ response[:msg].should == 'Command completed successfully'
+ response[:result_code].should == '1000'
+
+ Contact.last.ident_type.should == 'birthday'
+ end
+
+ it 'successfully adds registrar' do
+ response = create_request
+
+ response[:msg].should == 'Command completed successfully'
+ response[:result_code].should == '1000'
+
+ Contact.last.registrar.should == @registrar1
+ end
+
+ it 'returns result data upon success' do
+ response = create_request
+
+ response[:msg].should == 'Command completed successfully'
+ response[:result_code].should == '1000'
+
+ id = response[:parsed].css('resData creData id').first
+ cr_date = response[:parsed].css('resData creData crDate').first
+
+ id.text.length.should == 8
+ # 5 seconds for what-ever weird lag reasons might happen
+ cr_date.text.to_time.should be_within(5).of(Time.now)
+ end
+
+ it 'successfully saves custom code' do
+ response = create_request(
+ { id: { value: '12345' } }
+ )
+
+ response[:msg].should == 'Command completed successfully'
+ response[:result_code].should == '1000'
+
+ Contact.last.code.should == 'registrar1:12345'
+ end
+ end
+
+ context 'update command' do
+ before :all do
+ @contact =
+ Fabricate(
+ :contact,
+ registrar: @registrar1,
+ email: 'not_updated@test.test',
+ code: 'sh8013'
+ )
+ end
+
+ def update_request(overwrites = {})
+ defaults = {
+ id: { value: 'asd123123er' },
+ authInfo: { pw: { value: 'password' } },
+ chg: {
+ postalInfo: {
+ name: { value: 'John Doe Edited' }
+ },
+ voice: { value: '+372.7654321' },
+ email: { value: 'edited@example.example' },
+ disclose: {
+ value: {
+ voice: { value: '' },
+ email: { value: '' }
+ }, attrs: { flag: '0' }
+ }
+ }
+ }
+ update_xml = @epp_xml.update(defaults.deep_merge(overwrites), @legal_document)
+ epp_plain_request(update_xml, :xml)
+ end
+
+ it 'fails if request is invalid' do
+ response = epp_plain_request(@epp_xml.update, :xml)
+
+ response[:results][0][:msg].should ==
+ 'Required parameter missing: add, rem or chg'
+ response[:results][0][:result_code].should == '2003'
+ response[:results][1][:msg].should ==
+ 'Required parameter missing: update > update > id [id]'
+ response[:results][1][:result_code].should == '2003'
+ response[:results][2][:msg].should ==
+ 'Required parameter missing: update > update > authInfo > pw [pw]'
+ response[:results][2][:result_code].should == '2003'
+ response[:results][3][:msg].should ==
+ 'Required parameter missing: extension > extdata > legalDocument [legal_document]'
+ response[:results][3][:result_code].should == '2003'
+ response[:results].count.should == 4
+ end
+
+ it 'returns error if obj doesnt exist' do
+ response = update_request({ id: { value: 'not-exists' } })
+ response[:msg].should == 'Object does not exist'
+ response[:result_code].should == '2303'
+ response[:results].count.should == 1
+ end
+
+ it 'is succesful' do
+ response = update_request({ id: { value: 'sh8013' } })
+
+ response[:msg].should == 'Command completed successfully'
+ @contact.reload
+ @contact.name.should == 'John Doe Edited'
+ @contact.email.should == 'edited@example.example'
+ end
+
+ it 'fails with wrong authentication info' do
+ login_as :registrar2 do
+ response = update_request({ id: { value: 'sh8013' } })
+ response[:msg].should == 'Authorization error'
+ response[:result_code].should == '2201'
+ end
+ end
+
+ it 'returns phone and email error' do
+ response = update_request({
+ id: { value: 'sh8013' },
+ chg: {
+ voice: { value: '123213' },
+ email: { value: 'wrong' }
+ }
+ })
+
+ response[:results][0][:msg].should == 'Phone nr is invalid [phone]'
+ response[:results][0][:result_code].should == '2005'
+ response[:results][1][:msg].should == 'Email is invalid [email]'
+ response[:results][1][:result_code].should == '2005'
+ end
+
+ it 'should not update code with custom string' do
+ response = update_request(
+ id: { value: 'sh8013' },
+ chg: {
+ id: { value: 'notpossibletoupdate' }
+ }
+ )
+
+ response[:msg].should == 'Object does not exist'
+ response[:result_code].should == '2303'
+
+ @contact.reload.code.should == 'sh8013'
+ end
+ end
+
+ context 'delete command' do
+ before do
+ @contact = Fabricate(:contact, registrar: @registrar1)
+ end
+
+ def delete_request(overwrites = {})
+ defaults = {
+ id: { value: @contact.code },
+ authInfo: { pw: { value: @contact.auth_info } }
+ }
+ delete_xml = @epp_xml.delete(defaults.deep_merge(overwrites), @legal_document)
+ epp_plain_request(delete_xml, :xml)
+ end
+
+ it 'fails if request is invalid' do
+ response = epp_plain_request(@epp_xml.delete, :xml)
+
+ response[:results][0][:msg].should ==
+ 'Required parameter missing: delete > delete > id [id]'
+ response[:results][0][:result_code].should == '2003'
+ response[:results][1][:msg].should ==
+ 'Required parameter missing: delete > delete > authInfo > pw [pw]'
+ response[:results][1][:result_code].should == '2003'
+ response[:results][2][:msg].should ==
+ 'Required parameter missing: extension > extdata > legalDocument [legal_document]'
+ response[:results][2][:result_code].should == '2003'
+ response[:results].count.should == 3
+ end
+
+ it 'returns error if obj doesnt exist' do
+ response = delete_request({ id: { value: 'not-exists' } })
+ response[:msg].should == 'Object does not exist'
+ response[:result_code].should == '2303'
+ response[:results].count.should == 1
+ end
+
+ it 'deletes contact' do
+ response = delete_request
+ response[:msg].should == 'Command completed successfully'
+ response[:result_code].should == '1000'
+ response[:clTRID].should == 'ABC-12345'
+
+ Contact.find_by_id(@contact.id).should == nil
+ end
+
+ it 'fails if contact has associated domain' do
+ @domain = Fabricate(:domain, registrar: @registrar1, owner_contact: @contact)
+ @domain.owner_contact.address.present?.should == true
+
+ response = delete_request
+ response[:msg].should == 'Object association prohibits operation [domains]'
+ response[:result_code].should == '2305'
+ response[:results].count.should == 1
+
+ @domain.owner_contact.present?.should == true
+ end
+
+ it 'fails with wrong authentication info' do
+ login_as :registrar2 do
+ response = delete_request
+ response[:msg].should == 'Authorization error'
+ response[:result_code].should == '2201'
+ response[:results].count.should == 1
+ end
+ end
+ end
+
+ context 'check command' do
+ def check_request(overwrites = {})
+ defaults = {
+ id: { value: @contact.code },
+ authInfo: { pw: { value: @contact.auth_info } }
+ }
+ xml = @epp_xml.check(defaults.deep_merge(overwrites))
+ epp_plain_request(xml, :xml)
+ end
+
+ it 'fails if request is invalid' do
+ response = epp_plain_request(@epp_xml.check, :xml)
+
+ response[:results][0][:msg].should == 'Required parameter missing: check > check > id [id]'
+ response[:results][0][:result_code].should == '2003'
+ response[:results].count.should == 1
+ end
+
+ it 'returns info about contact availability' do
+ Fabricate(:contact, code: 'check-1234')
+
+ response = epp_plain_request(check_multiple_contacts_xml, :xml)
+
+ response[:msg].should == 'Command completed successfully'
+ response[:result_code].should == '1000'
+ ids = response[:parsed].css('resData chkData id')
+
+ ids[0].attributes['avail'].text.should == '0'
+ ids[1].attributes['avail'].text.should == '1'
+
+ ids[0].text.should == 'check-1234'
+ ids[1].text.should == 'check-4321'
+ end
+ end
+
+ context 'info command' do
+ def info_request(overwrites = {})
+ defaults = {
+ id: { value: @contact.code },
+ authInfo: { pw: { value: @contact.auth_info } }
+ }
+ xml = @epp_xml.info(defaults.deep_merge(overwrites))
+ epp_plain_request(xml, :xml)
+ end
+
+ it 'fails if request invalid' do
+ response = epp_plain_request(@epp_xml.info, :xml)
+ response[:results][0][:msg].should ==
+ 'Required parameter missing: info > info > id [id]'
+ response[:results][0][:result_code].should == '2003'
+ response[:results].count.should == 1
+ end
+
+ it 'returns error when object does not exist' do
+ response = info_request({ id: { value: 'no-contact' } })
+ response[:msg].should == 'Object does not exist'
+ response[:result_code].should == '2303'
+ response[:results][0][:value].should == 'no-contact'
+ response[:results].count.should == 1
+ end
+
+ it 'return info about contact' do
+ @registrar1_contact = Fabricate(
+ :contact, code: 'info-4444', registrar: @registrar1,
+ name: 'Johnny Awesome', address: Fabricate(:address))
+
+ response = info_request({ id: { value: @registrar1_contact.code } })
+ response[:msg].should == 'Command completed successfully'
+ response[:result_code].should == '1000'
+
+ contact = response[:parsed].css('resData chkData')
+ contact.css('name').first.text.should == 'Johnny Awesome'
+ end
+
+ it 'returns no authorization error for wrong password when owner' do
+ response = info_request({ authInfo: { pw: { value: 'wrong-pw' } } })
+
+ response[:msg].should == 'Command completed successfully'
+ response[:result_code].should == '1000'
+ response[:results].count.should == 1
+ end
+
+ it 'returns no authorization error for wrong user but correct pw' do
+ login_as :registrar2 do
+ response = info_request
+
+ response[:msg].should == 'Command completed successfully'
+ response[:result_code].should == '1000'
+ response[:results].count.should == 1
+ end
+ end
+
+ it 'returns authorization error for wrong user and wrong pw' do
+ login_as :registrar2 do
+ response = info_request({ authInfo: { pw: { value: 'wrong-pw' } } })
+ response[:msg].should == 'Authorization error'
+ response[:result_code].should == '2201'
+ response[:results].count.should == 1
+ end
+ end
+ end
+
+ context 'renew command' do
+ it 'returns 2101-unimplemented command' do
+ response = epp_plain_request('contacts/renew.xml')
+
+ response[:msg].should == 'Unimplemented command'
+ response[:result_code].should == '2101'
+ end
+ end
+ end
+
+ def check_multiple_contacts_xml
+ '
+
+
+
+
+ check-1234
+ check-4321
+
+
+ ABC-12345
+
+ '
+ end
+end
diff --git a/spec/epp/domain_spec.rb b/spec/epp/domain_spec.rb
index 5ba4c4159..1b03e2487 100644
--- a/spec/epp/domain_spec.rb
+++ b/spec/epp/domain_spec.rb
@@ -11,12 +11,10 @@ describe 'EPP Domain', epp: true do
login_as :registrar1
- Contact.skip_callback(:create, :before, :generate_code)
-
Fabricate(:contact, code: 'citizen_1234')
Fabricate(:contact, code: 'sh8013')
Fabricate(:contact, code: 'sh801333')
- Fabricate(:contact, code: 'juridical_1234', ident_type: 'ico')
+ Fabricate(:contact, code: 'juridical_1234', ident_type: 'bic')
Fabricate(:reserved_domain)
@uniq_no = proc { @i ||= 0; @i += 1 }
@@ -61,16 +59,20 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml)
response[:results][0][:result_code].should == '2003'
- response[:results][0][:msg].should == 'Required parameter missing: create > create > ns'
+ response[:results][0][:msg].should ==
+ 'Required parameter missing: create > create > ns [ns]'
response[:results][1][:result_code].should == '2003'
- response[:results][1][:msg].should == 'Required parameter missing: create > create > registrant'
+ response[:results][1][:msg].should ==
+ 'Required parameter missing: create > create > registrant [registrant]'
response[:results][2][:result_code].should == '2003'
- response[:results][2][:msg].should == 'Required parameter missing: create > create > ns > hostAttr'
+ response[:results][2][:msg].should ==
+ 'Required parameter missing: create > create > ns > hostAttr [host_attr]'
response[:results][3][:result_code].should == '2003'
- response[:results][3][:msg].should == 'Required parameter missing: extension > extdata > legalDocument'
+ response[:results][3][:msg].should ==
+ 'Required parameter missing: extension > extdata > legalDocument [legal_document]'
end
context 'with citizen as an owner' do
@@ -169,7 +171,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml)
response[:result_code].should == '2306'
- response[:msg].should == 'IPv4 is missing'
+ response[:msg].should == 'IPv4 is missing [ipv4]'
end
# it 'does not create duplicate domain' do
@@ -191,7 +193,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml)
response[:result_code].should == '2302'
- response[:msg].should == 'Domain name is reserved or restricted'
+ response[:msg].should == 'Domain name is reserved or restricted [name_dirty]'
response[:clTRID].should == 'ABC-12345'
end
@@ -200,14 +202,23 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml)
response[:results][0][:result_code].should == '2003'
- response[:results][0][:msg].should == 'Required parameter missing: create > create > registrant'
+ response[:results][0][:msg].should ==
+ 'Required parameter missing: create > create > registrant [registrant]'
end
it 'does not create domain without nameservers' do
xml = domain_create_xml(ns: [])
response = epp_plain_request(xml, :xml)
- response[:result_code].should == '2003'
- response[:msg].should == 'Required parameter missing: create > create > ns > hostAttr'
+
+ response[:results][0][:msg].should ==
+ 'Required parameter missing: create > create > ns [ns]'
+ response[:results][0][:result_code].should == '2003'
+
+ response[:results][1][:msg].should ==
+ 'Required parameter missing: create > create > ns > hostAttr [host_attr]'
+ response[:results][1][:result_code].should == '2003'
+
+ response[:results].count.should == 2
end
it 'does not create domain with too many nameservers' do
@@ -226,7 +237,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml)
response[:result_code].should == '2004'
- response[:msg].should == 'Nameservers count must be between 2-11'
+ response[:msg].should == 'Nameservers count must be between 2-11 [nameservers]'
end
it 'returns error when invalid nameservers are present' do
@@ -246,8 +257,8 @@ describe 'EPP Domain', epp: true do
})
response = epp_plain_request(xml, :xml)
+ response[:msg].should == 'Hostname is invalid [hostname]'
response[:result_code].should == '2005'
- response[:msg].should == 'Hostname is invalid'
end
it 'checks hostAttr presence' do
@@ -263,8 +274,8 @@ describe 'EPP Domain', epp: true do
})
response = epp_plain_request(xml, :xml)
+ response[:msg].should == 'Required parameter missing: create > create > ns > hostAttr [host_attr]'
response[:result_code].should == '2003'
- response[:msg].should == 'Required parameter missing: create > create > ns > hostAttr'
end
it 'creates domain with nameservers with ips' do
@@ -280,10 +291,10 @@ describe 'EPP Domain', epp: true do
nameserver_count = Nameserver.count
response = epp_plain_request(domain_create_with_invalid_ns_ip_xml, :xml)
response[:results][0][:result_code].should == '2005'
- response[:results][0][:msg].should == 'IPv4 is invalid'
+ response[:results][0][:msg].should == 'IPv4 is invalid [ipv4]'
response[:results][0][:value].should == '192.0.2.2.invalid'
response[:results][1][:result_code].should == '2005'
- response[:results][1][:msg].should == 'IPv6 is invalid'
+ response[:results][1][:msg].should == 'IPv6 is invalid [ipv6]'
response[:results][1][:value].should == 'INVALID_IPV6'
# ensure nothing gets saved to db:
Domain.count.should == domain_count
@@ -294,8 +305,8 @@ describe 'EPP Domain', epp: true do
xml = domain_create_xml(period_value: 365, period_unit: 'd')
response = epp_plain_request(xml, :xml)
- response[:result_code].should == '1000'
response[:msg].should == 'Command completed successfully'
+ response[:result_code].should == '1000'
Domain.first.valid_to.should == Date.today + 1.year
end
@@ -306,7 +317,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml)
response[:results][0][:result_code].should == '2004'
- response[:results][0][:msg].should == 'Period must add up to 1, 2 or 3 years'
+ response[:results][0][:msg].should == 'Period must add up to 1, 2 or 3 years [period]'
response[:results][0][:value].should == '367'
end
@@ -391,24 +402,25 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml)
- response[:results][0][:msg].should == 'Valid algorithms are: 3, 5, 6, 7, 8, 252, 253, 254, 255'
+ response[:results][0][:msg].should ==
+ 'Valid algorithms are: 3, 5, 6, 7, 8, 252, 253, 254, 255 [alg]'
response[:results][0][:value].should == '9'
- response[:results][1][:msg].should == 'Valid protocols are: 3'
+ response[:results][1][:msg].should == 'Valid protocols are: 3 [protocol]'
response[:results][1][:value].should == '4'
- response[:results][2][:msg].should == 'Valid flags are: 0, 256, 257'
+ response[:results][2][:msg].should == 'Valid flags are: 0, 256, 257 [flags]'
response[:results][2][:value].should == '250'
- response[:results][3][:msg].should == 'Valid algorithms are: 3, 5, 6, 7, 8, 252, 253, 254, 255'
+ response[:results][3][:msg].should == 'Valid algorithms are: 3, 5, 6, 7, 8, 252, 253, 254, 255 [alg]'
response[:results][3][:value].should == '10'
- response[:results][4][:msg].should == 'Valid flags are: 0, 256, 257'
+ response[:results][4][:msg].should == 'Valid flags are: 0, 256, 257 [flags]'
response[:results][4][:value].should == '1'
- response[:results][5][:msg].should == 'Public key is missing'
+ response[:results][5][:msg].should == 'Public key is missing [public_key]'
- response[:results][6][:msg].should == 'Valid protocols are: 3'
+ response[:results][6][:msg].should == 'Valid protocols are: 3 [protocol]'
response[:results][6][:value].should == '5'
end
@@ -435,7 +447,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml)
response[:result_code].should == '2302'
- response[:msg].should == 'Public key already exists'
+ response[:msg].should == 'Public key already exists [public_key]'
response[:results][0][:value].should == '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f'
end
@@ -464,7 +476,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml)
response[:result_code].should == '2004'
- response[:msg].should == 'DNS keys count must be between 0-1'
+ response[:msg].should == 'DNS keys count must be between 0-1 [dnskeys]'
create_settings
end
@@ -661,8 +673,8 @@ describe 'EPP Domain', epp: true do
})
response = epp_plain_request(xml, :xml)
+ response[:msg].should == 'Admin contacts count must be between 1-10 [admin_contacts]'
response[:result_code].should == '2004'
- response[:msg].should == 'Admin contacts count must be between 1-10'
response[:clTRID].should == 'ABC-12345'
Domain.count.should == domain_count
@@ -678,8 +690,8 @@ describe 'EPP Domain', epp: true do
})
response = epp_plain_request(xml, :xml)
- response[:result_code].should == '2306'
response[:msg].should == 'Admin contact can be only citizen'
+ response[:result_code].should == '2306'
end
end
@@ -853,7 +865,8 @@ describe 'EPP Domain', epp: true do
login_as :registrar2 do
response = epp_plain_request(xml, :xml)
response[:result_code].should == '2003'
- response[:msg].should == 'Required parameter missing: extension > extdata > legalDocument'
+ response[:msg].should ==
+ 'Required parameter missing: extension > extdata > legalDocument [legal_document]'
end
end
@@ -970,7 +983,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml)
response[:result_code].should == '2201'
- response[:msg].should == 'Authorization error'
+ response[:msg].should == 'Authorization error [auth_info]'
end
it 'ignores transfer when owner registrar requests transfer' do
@@ -1017,7 +1030,7 @@ describe 'EPP Domain', epp: true do
epp_plain_request(xml, :xml) # transfer domain
response = epp_plain_request(xml, :xml) # attempt second transfer
response[:result_code].should == '2201'
- response[:msg].should == 'Authorization error'
+ response[:msg].should == 'Authorization error [auth_info]'
end
end
@@ -1120,27 +1133,27 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml)
response[:results][0][:result_code].should == '2302'
- response[:results][0][:msg].should == 'Nameserver already exists on this domain'
+ response[:results][0][:msg].should == 'Nameserver already exists on this domain [hostname]'
response[:results][0][:value].should == 'ns1.example.com'
response[:results][1][:result_code].should == '2302'
- response[:results][1][:msg].should == 'Nameserver already exists on this domain'
+ response[:results][1][:msg].should == 'Nameserver already exists on this domain [hostname]'
response[:results][1][:value].should == 'ns2.example.com'
response[:results][2][:result_code].should == '2302'
- response[:results][2][:msg].should == 'Contact already exists on this domain'
+ response[:results][2][:msg].should == 'Contact already exists on this domain [contact_code_cache]'
response[:results][2][:value].should == 'mak21'
- response[:results][3][:msg].should == 'Status already exists on this domain'
+ response[:results][3][:msg].should == 'Status already exists on this domain [value]'
response[:results][3][:value].should == 'clientHold'
- response[:results][4][:msg].should == 'Status already exists on this domain'
+ response[:results][4][:msg].should == 'Status already exists on this domain [value]'
response[:results][4][:value].should == 'clientUpdateProhibited'
- response[:results][5][:msg].should == 'Public key already exists'
+ response[:results][5][:msg].should == 'Public key already exists [public_key]'
response[:results][5][:value].should == '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f'
- response[:results][6][:msg].should == 'Public key already exists'
+ response[:results][6][:msg].should == 'Public key already exists [public_key]'
response[:results][6][:value].should == '841936717ae427ace63c28d04918569a841936717ae427ace63c28d0'
d.domain_statuses.count.should == 2
@@ -1292,11 +1305,11 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml)
response[:results][0][:result_code].should == '2302'
- response[:results][0][:msg].should == 'Nameserver already exists on this domain'
+ response[:results][0][:msg].should == 'Nameserver already exists on this domain [hostname]'
response[:results][0][:value].should == n.hostname
response[:results][1][:result_code].should == '2302'
- response[:results][1][:msg].should == 'Contact already exists on this domain'
+ response[:results][1][:msg].should == 'Contact already exists on this domain [contact_code_cache]'
response[:results][1][:value].should == c.code
end
@@ -1309,7 +1322,8 @@ describe 'EPP Domain', epp: true do
}
response = epp_plain_request(domain_update_xml(xml_params), :xml)
- response[:results][0][:msg].should == 'Required parameter missing: extension > extdata > legalDocument'
+ response[:results][0][:msg].should ==
+ 'Required parameter missing: extension > extdata > legalDocument [legal_document]'
response[:results][0][:result_code].should == '2003'
end
@@ -1366,7 +1380,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml)
response[:results][0][:result_code].should == '2004'
- response[:results][0][:msg].should == 'Period must add up to 1, 2 or 3 years'
+ response[:results][0][:msg].should == 'Period must add up to 1, 2 or 3 years [period]'
response[:results][0][:value].should == '4'
end
@@ -1518,7 +1532,8 @@ describe 'EPP Domain', epp: true do
it 'does not delete domain without legal document' do
response = epp_plain_request(@epp_xml.domain.delete(name: { value: 'example.ee' }), :xml)
response[:result_code].should == '2003'
- response[:msg].should == 'Required parameter missing: extension > extdata > legalDocument'
+ response[:msg].should ==
+ 'Required parameter missing: extension > extdata > legalDocument [legal_document]'
end
### CHECK ###
diff --git a/spec/epp/keyrelay_spec.rb b/spec/epp/keyrelay_spec.rb
index 7d513391b..731873d08 100644
--- a/spec/epp/keyrelay_spec.rb
+++ b/spec/epp/keyrelay_spec.rb
@@ -64,7 +64,7 @@ describe 'EPP Keyrelay', epp: true do
})
response = epp_plain_request(xml, :xml)
- response[:msg].should == 'Required parameter missing: keyrelay > keyData > flags'
+ response[:msg].should == 'Required parameter missing: keyrelay > keyData > flags [flags]'
@registrar2.messages.queued.count.should == msg_count
end
diff --git a/spec/epp/session_spec.rb b/spec/epp/session_spec.rb
index 2da903652..e0e8afae9 100644
--- a/spec/epp/session_spec.rb
+++ b/spec/epp/session_spec.rb
@@ -35,6 +35,7 @@ describe 'EPP Session', epp: true do
inactive = @epp_xml.session.login(clID: { value: 'inactive-user' }, pw: { value: 'ghyt9e4fu' })
response = epp_plain_request(inactive, :xml)
+ response[:msg].should == 'Authentication error; server closing connection'
response[:result_code].should == '2501'
end
diff --git a/spec/fabricators/certificate_fabricator.rb b/spec/fabricators/certificate_fabricator.rb
new file mode 100644
index 000000000..8e97b9ec5
--- /dev/null
+++ b/spec/fabricators/certificate_fabricator.rb
@@ -0,0 +1,33 @@
+# default fabricator should be reusable
+Fabricator(:certificate) do
+ api_user
+ csr "-----BEGIN CERTIFICATE REQUEST-----\n" \
+ "MIIE+DCCAuACAQAwgZ0xCzAJBgNVBAYTAkVFMREwDwYDVQQIDAhIYXJqdW1hYTEQ\n" \
+ "MA4GA1UEBwwHVGFsbGlubjEbMBkGA1UECgwSRWVzdGkgSW50ZXJuZXRpIFNBMRIw\n" \
+ "EAYDVQQLDAlSRUdJU1RSQVIxEjAQBgNVBAMMCXdlYmNsaWVudDEkMCIGCSqGSIb3\n" \
+ "DQEJARYVd2ViY2xpZW50QGludGVybmV0LmVlMIICIjANBgkqhkiG9w0BAQEFAAOC\n" \
+ "Ag8AMIICCgKCAgEAuXronFj8CxPWGkyUhXf+/WirkFGb8a/My2+7GvQWYE10Nq4C\n" \
+ "u9wDgjU3AuLw8qzwEeE3Z5uxHXWfwnshXOF6aJNCQWUsrs0odCxw69iIwCNGKhyF\n" \
+ "jljtx8uSH8RRSRc8BFIUkvUpmp8m7kZTlB4FDey+XaGy4p/rImiAiwfFMIJMjdE9\n" \
+ "9gk0EGDbomgP6KC3Ss/iQfuOFCQWSqjFuvp3mygr193YplaPgeLM1ERIW1LVFGDK\n" \
+ "jy6keZ3E/Vb4O4qUPDRgTMr2KWM3Auzh2hXCymHNWn3yRn5Q4KSjJbG/P7Kz5nfZ\n" \
+ "kY3eVRBIBll+1Q0VV7g+1B48zzjZX2qiY3iL77MV1oL17KeOO3PAxsEtptdqNgUa\n" \
+ "Fpp73dwPST1ZKvq8FSgDKcdTCziSeViGhXjJRpEMr8FoeKNO7nvd1maKN9HAOy75\n" \
+ "eSxatj6LoQ+JFN7Ci3IbwKFI7BnIHbEr9eP7O7Qbhljz2GE9+GWUqr3zwUEgpFSI\n" \
+ "crAnRHQI2ALakEMsryF416zg5yr/bJp8/IzgZLaKpBVLOL88sI6r+JRdM6QXvKYx\n" \
+ "XhamV6bH6CrR8ZYN4okaZH6sAcy8eyBnEmc05h/KsDzTNadwadeZe73F+PltoEXH\n" \
+ "XgtpTpQ8XarN1uLq99WD6gWilAx3LF/xetCO86+w/MkYBmfOrXge+WLUUW8CAwEA\n" \
+ "AaAVMBMGCSqGSIb3DQEJBzEGDAR0ZXN0MA0GCSqGSIb3DQEBCwUAA4ICAQAkTlU3\n" \
+ "RcI6UMRA7As2FJSph3QurPebQFoZhnhMD+hb6+hXip8MY77YxLwo/ihB9wghaZKL\n" \
+ "uV0BxjdZgjDt9GhA8dtPgaCp5LvB6kQYvcEzRvitN2CpJhtz39rlF3gxuy+RtpNf\n" \
+ "5KbC691FivoXur1qx9I7mc4snB3DTzLiJPIZ6nQzPYcSVpPCbns30N/i/sOdHO0o\n" \
+ "9hP5wlhCdYrOxad993m+InpMDyDWhB1+TA9ZO7gYpg8S4kBX3Cz9OXe80Pe56ZdK\n" \
+ "pcgjTXnUDjNSRRGamJib2lyZ/axMbb/etwyy3X+jBDuOQropkmgrPEFJHpgNlFah\n" \
+ "BuW7KEASqbw5YxpTSc0nDk5uxBw3voL8fk9M1sX64tbzGAEBRZnrWGeb1mOLM/YI\n" \
+ "K6ocAYSBhNmWUzpHTwL7qSeP9ztQUGzoGHyRjBdan+1U2G75Kpj+TjEm/X8wmtnq\n" \
+ "3/qVhUYNEavcZbgR1gSE45+mS8NsD7Oq0Xdc0UKsVDbUcCGIkGG9+ERAbRznfi3W\n" \
+ "qhChtUxySX8T3SmX5mviwlJ5OwQVjdUF1/2voPK0oFK7zV+wZqcuORzDKdqB8XV7\n" \
+ "MDcQjza4EOB78OmcHDgQ7nMXuY7/UL4F+bRZosxPy43X2JId5d+/GpgV8sP9dzK8\n" \
+ "UGJDNEZ2YsBbPuKZS+2eNZ8g3sjjFBeadvrQ1w==\n" \
+ "-----END CERTIFICATE REQUEST-----"
+end
diff --git a/spec/fabricators/contact_fabricator.rb b/spec/fabricators/contact_fabricator.rb
index c483ad554..45c4db75e 100644
--- a/spec/fabricators/contact_fabricator.rb
+++ b/spec/fabricators/contact_fabricator.rb
@@ -1,12 +1,16 @@
Fabricator(:contact) do
+ code { "sh#{Faker::Number.number(8)}" }
+ auth_info 'password'
name { sequence(:name) { |i| "#{Faker::Name.name}#{i}" } }
phone '+372.12345678'
email Faker::Internet.email
ident '37605030299'
- code { "sh#{Faker::Number.number(8)}" }
- ident_type 'op'
- auth_info 'ccds4324pok'
+ ident_type 'priv'
+ ident_country_code 'EE'
address
registrar { Fabricate(:registrar, name: Faker::Company.name, reg_no: Faker::Company.duns_number) }
disclosure { Fabricate(:contact_disclosure) }
+ # rubocop: disable Style/SymbolProc
+ after_validation { |c| c.disable_generate_auth_info! }
+ # rubocop: enamble Style/SymbolProc
end
diff --git a/spec/fabricators/domain_fabricator.rb b/spec/fabricators/domain_fabricator.rb
index d6197b6e4..fd5c209e6 100644
--- a/spec/fabricators/domain_fabricator.rb
+++ b/spec/fabricators/domain_fabricator.rb
@@ -1,5 +1,5 @@
Fabricator(:domain) do
- name { "#{Faker::Internet.domain_word}.ee" }
+ name { "fabricate_name#{rand(1_000_000)}.ee" }
valid_to Date.new(2014, 8, 7)
period 1
period_unit 'y'
diff --git a/spec/models/api_user_spec.rb b/spec/models/api_user_spec.rb
index a6c6fb102..9fb0d2fdc 100644
--- a/spec/models/api_user_spec.rb
+++ b/spec/models/api_user_spec.rb
@@ -20,6 +20,11 @@ describe ApiUser do
it 'should not have any versions' do
@api_user.versions.should == []
end
+
+ it 'should be active by default' do
+ @api_user.active.should == true
+ end
+
end
context 'with valid attributes' do
diff --git a/spec/models/certificate_spec.rb b/spec/models/certificate_spec.rb
new file mode 100644
index 000000000..26656e51b
--- /dev/null
+++ b/spec/models/certificate_spec.rb
@@ -0,0 +1,61 @@
+require 'rails_helper'
+
+describe Certificate do
+ it { should belong_to(:api_user) }
+
+ context 'with invalid attribute' do
+ before :all do
+ @certificate = Certificate.new
+ end
+
+ it 'should not be valid' do
+ @certificate.valid?
+ @certificate.errors.full_messages.should match_array([
+ "Csr is missing"
+ ])
+ end
+
+ it 'should not have any versions' do
+ @certificate.versions.should == []
+ end
+ end
+
+ context 'with valid attributes' do
+ before :all do
+ @certificate = Fabricate(:certificate)
+ end
+
+ it 'should be valid' do
+ @certificate.valid?
+ @certificate.errors.full_messages.should match_array([])
+ end
+
+ it 'should be valid twice' do
+ @certificate = Fabricate(:certificate)
+ @certificate.valid?
+ @certificate.errors.full_messages.should match_array([])
+ end
+
+ it 'should sign csr', epp: true do
+ @certificate.status.should == 'unsigned'
+ @certificate.sign!
+ @certificate.status.should == 'signed'
+ @certificate.crt.should_not be_blank
+ end
+
+ it 'should revoke crt', epp: true do
+ @certificate.revoke!
+ @certificate.status.should == 'revoked'
+ end
+
+ it 'should have one version' do
+ with_versioning do
+ @certificate.versions.should == []
+ @certificate.csr = 'new_request'
+ @certificate.save
+ @certificate.errors.full_messages.should match_array([])
+ @certificate.versions.size.should == 1
+ end
+ end
+ end
+end
diff --git a/spec/models/contact_disclosure_spec.rb b/spec/models/contact_disclosure_spec.rb
deleted file mode 100644
index f8c268fca..000000000
--- a/spec/models/contact_disclosure_spec.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-require 'rails_helper'
-
-describe ContactDisclosure do
- it { should belong_to(:contact) }
-
- context 'about class' do
- it 'should have versioning enabled?' do
- ContactDisclosure.paper_trail_enabled_for_model?.should == true
- end
-
- it 'should have custom log prexied table name for versions table' do
- ContactDisclosureVersion.table_name.should == 'log_contact_disclosures'
- end
- end
-
- context 'with invalid attribute' do
- before :all do
- @contact_disclosure = ContactDisclosure.new
- end
-
- it 'should not be valid' do
- @contact_disclosure.valid?
- @contact_disclosure.errors.full_messages.should match_array([
- ])
- end
-
- it 'should not have any versions' do
- @contact_disclosure.versions.should == []
- end
- end
-
- context 'with valid attributes' do
- before :all do
- @contact_disclosure = Fabricate(:contact_disclosure)
- end
-
- it 'should be valid' do
- @contact_disclosure.valid?
- @contact_disclosure.errors.full_messages.should match_array([])
- end
-
- it 'should be valid twice' do
- @contact_disclosure = Fabricate(:contact_disclosure)
- @contact_disclosure.valid?
- @contact_disclosure.errors.full_messages.should match_array([])
- end
-
- it 'should have one version' do
- with_versioning do
- @contact_disclosure.versions.should == []
- @contact_disclosure.name = false
- @contact_disclosure.save
- @contact_disclosure.errors.full_messages.should match_array([])
- @contact_disclosure.versions.size.should == 1
- end
- end
- end
-
-end
-
-describe '.extract_attributes' do
- it 'should return empty hash for empty arguments' do
- result = ContactDisclosure.extract_attributes(Nokogiri::XML::Document.new)
- expect(result).to eq({})
- end
-
- it 'should return empty hash if no disclosure' do
- parsed_frame = Nokogiri::XML(create_contact_xml).remove_namespaces!
- result = ContactDisclosure.extract_attributes(parsed_frame)
- expect(result).to eq({})
- end
-
- # TODO: remodel create contact xml to support disclosure
- it 'should return disclosure has if disclosure' do
- epp_xml = EppXml::Contact.new
- xml = epp_xml.create(
- {
- disclose: { value: {
- voice: { value: '' },
- addr: { value: '' },
- name: { value: '' },
- org_name: { value: '' },
- email: { value: '' },
- fax: { value: '' }
- }, attrs: { flag: '0' }
- } })
- parsed_frame = Nokogiri::XML(xml).remove_namespaces!
- result = ContactDisclosure.extract_attributes(parsed_frame)
- expect(result).to eq({ phone: '0', email: '0', fax: '0', address: '0', name: '0', org_name: '0' })
- end
-end
diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb
index 58b54cacf..dbf7bc3dc 100644
--- a/spec/models/contact_spec.rb
+++ b/spec/models/contact_spec.rb
@@ -39,11 +39,11 @@ describe Contact do
end
it 'should not have creator' do
- @contact.cr_id.should == nil
+ @contact.creator.should == nil
end
it 'should not have updater' do
- @contact.up_id.should == nil
+ @contact.updator.should == nil
end
it 'phone should return false' do
@@ -52,9 +52,51 @@ describe Contact do
@contact.errors[:phone].should == ["Phone nr is invalid"]
end
+ it 'should require country code when bic' do
+ @contact.ident_type = 'bic'
+ @contact.valid?
+ @contact.errors[:ident_country_code].should == ['is missing']
+ end
+
+ it 'should require country code when priv' do
+ @contact.ident_type = 'priv'
+ @contact.valid?
+ @contact.errors[:ident_country_code].should == ['is missing']
+ end
+
+ it 'should validate correct country code' do
+ @contact.ident_type = 'bic'
+ @contact.ident_country_code = 'EE'
+ @contact.valid?
+
+ @contact.errors[:ident_country_code].should == []
+ end
+
+ it 'should require valid country code' do
+ @contact.ident_type = 'bic'
+ @contact.ident_country_code = 'INVALID'
+ @contact.valid?
+
+ @contact.errors[:ident_country_code].should == ['is not following ISO_3166-1 alpha 2 format']
+ end
+
+ it 'should convert to alpha2 country code' do
+ @contact.ident_type = 'bic'
+ @contact.ident_country_code = 'ee'
+ @contact.valid?
+
+ @contact.ident_country_code.should == 'EE'
+ end
+
it 'should not have any versions' do
@contact.versions.should == []
end
+
+ it 'should not accept long code' do
+ @contact.code = 'verylongcode' * 100
+ @contact.valid?
+ @contact.errors[:code].should == ['is too long (maximum is 100 characters)']
+ end
end
context 'with valid attributes' do
@@ -87,18 +129,23 @@ describe Contact do
@contact.relations_with_domain?.should == false
end
- # it 'ico should be valid' do
- # @contact.ident_type = 'ico'
- # @contact.ident = '1234'
- # @contact.errors.full_messages.should match_array([])
- # end
+ it 'bic should be valid' do
+ @contact.ident_type = 'bic'
+ @contact.ident = '1234'
+ @contact.valid?
+ @contact.errors.full_messages.should match_array([])
+ end
- # it 'ident should return false' do
- # puts @contact.ident_type
- # @contact.ident = '123abc'
- # @contact.valid?
- # @contact.errors.full_messages.should_not == []
- # end
+ it 'should not accept new custom code' do
+ old_code = @contact.code
+ @contact.code = 'CID:REG1:12345'
+ @contact.save.should == true
+ @contact.code.should == old_code
+ end
+
+ it 'should have static password' do
+ @contact.auth_info.should == 'password'
+ end
context 'as birthday' do
before :all do
@@ -119,7 +166,8 @@ describe Contact do
invalid.each do |date|
@contact.ident = date
@contact.valid?
- @contact.errors.full_messages.should == ["Ident is invalid"]
+ @contact.errors.full_messages.should ==
+ ["Ident Ident not in valid birthady format, should be YYYY-MM-DD"]
end
end
end
@@ -151,20 +199,56 @@ describe Contact do
end
context 'after create' do
- it 'should generate a new code and password' do
+ it 'should not generate a new code when code is present' do
+ @contact = Fabricate.build(:contact, code: '123asd', auth_info: 'qwe321')
+ @contact.code.should == '123asd'
+ @contact.save.should == true
+ @contact.code.should == '123asd'
+ end
+
+ it 'should generate a new password' do
@contact = Fabricate.build(:contact, code: '123asd', auth_info: 'qwe321')
- @contact.code.should == '123asd'
@contact.auth_info.should == 'qwe321'
- @contact.save!
- @contact.code.should_not == '123asd'
+ @contact.save.should == true
@contact.auth_info.should_not == 'qwe321'
end
+
+ it 'should not allow same code' do
+ @double_contact = Fabricate.build(:contact, code: @contact.code)
+ @double_contact.valid?
+ @double_contact.errors.full_messages.should == ["Code Contact id already exists"]
+ end
+
+ it 'should allow supported code format' do
+ @contact = Fabricate.build(:contact, code: 'CID:REG1:12345')
+ @contact.valid?
+ @contact.errors.full_messages.should == []
+ end
+
+ it 'should not allow unsupported characters in code' do
+ @contact = Fabricate.build(:contact, code: 'unsupported!ÄÖÜ~?')
+ @contact.valid?
+ @contact.errors.full_messages.should == ['Code is invalid']
+ end
+
+ it 'should generate code if empty code is given' do
+ @contact = Fabricate(:contact, code: '')
+ @contact.code.should_not == ''
+ end
+
+ it 'should not allow empty spaces as code' do
+ @contact = Fabricate.build(:contact, code: ' ')
+ @contact.valid?
+ @contact.errors.full_messages.should == ['Code is invalid']
+ end
end
context 'after update' do
before :all do
- @contact.code = '123asd'
- @contact.auth_info = 'qwe321'
+ @contact = Fabricate.build(:contact, code: '123asd', auth_info: 'qwe321')
+ @contact.save
+ @contact.code.should == '123asd'
+ @auth_info = @contact.auth_info
end
it 'should not generate new code' do
@@ -174,62 +258,13 @@ describe Contact do
it 'should not generate new auth_info' do
@contact.update_attributes(name: 'fvrsgbqevciherot23')
- @contact.auth_info.should == 'qwe321'
+ @contact.auth_info.should == @auth_info
end
end
-
- context 'with creator' do
- before :all do
- # @contact.created_by = @api_user
- end
-
- # TODO: change cr_id to something else
- it 'should return username of creator' do
- # @contact.cr_id.should == 'gitlab'
- end
- end
-
- context 'with updater' do
- before :all do
- # @contact.updated_by = @api_user
- end
-
- # TODO: change up_id to something else
- it 'should return username of updater' do
- # @contact.up_id.should == 'gitlab'
- end
-
- end
end
end
end
-# TODO: investigate it a bit more
-# describe Contact, '#relations_with_domain?' do
-# context 'with relation' do
-# before :all do
-# create_settings
-# Fabricate(:domain)
-# @contact = Fabricate(:contact)
-# end
-
-# it 'should have relation with domain' do
-# @contact.relations_with_domain?.should == true
-# end
-# end
-# end
-
-describe Contact, '.extract_params' do
- it 'returns params hash'do
- ph = { id: '123123', email: 'jdoe@example.com', authInfo: { pw: 'asde' },
- postalInfo: { name: 'fred', addr: { cc: 'EE' } } }
- Contact.extract_attributes(ph).should == {
- name: 'fred',
- email: 'jdoe@example.com'
- }
- end
-end
-
describe Contact, '.check_availability' do
before do
Fabricate(:contact, code: 'asd12')
diff --git a/spec/models/dnskey_spec.rb b/spec/models/dnskey_spec.rb
index 7b3302cab..dff7d84b2 100644
--- a/spec/models/dnskey_spec.rb
+++ b/spec/models/dnskey_spec.rb
@@ -61,22 +61,28 @@ describe Dnskey do
d = Fabricate(:domain, name: 'emta.ee', dnskeys: [@dnskey])
dk = d.dnskeys.last
- dk.public_key = 'AwEAAfB9jK8rj/FAdE3t9bYXiTLpelwlgUyxbHEtvMvhdxs+yHv0h9fE '\
- '710u94LPAeVmXumT6SZPsoo+ALKdmTexkcU9DGQvb2+sPfModBKM/num '\
- 'rScUw1FBe3HwRa9SqQpgpnCjIt0kEVKHAQdLOP86YznSA9uHAg9TTJuT '\
- 'LkUtgtmwNAVFr6/mG+smE1v5NbxPccsFwVTA/T1IyaI4Z48VGCP2WNro '\
- 'R7P6vet1gWhssirnnVYnur8DwWuMJ89o/HjzXeiEGUB8k5SOX+//67FN '\
- 'm8Zs+1ObuAfY8xAHe0L5bxluEbh1T1ARp41QX77EMKVbkcSj7nuBeY8H '\
- 'KiN8HsTvmZyDbRAQQaAJi68qOXsUIoQcpn89PoNoc60F7WlueA6ExSGX '\
- 'KMWIH6nfLXFgidoZ6HxteyUUnZbHEdULjpAoCRuUDjjUnUgFS7eRANfw '\
- 'RCcu9aLziMDp4UU61zVjtmQ7xn3G2W2+2ycqn/vEl/yFyBmHZ+7stpoC '\
- 'd6NTZUn4/ellYSm9lx/vaXdPSinARpYMWtU79Hu/VRifaCQjYkBGAMwK '\
- 'DshX4yJPjza/bqo0XV4WHj1szDFHe0tLN7g1Ojwtf5FR0zyHU3FN9uUa '\
- 'y8a+dowd/fqOQA1jXR04g2PIfFYe0VudCEpmxSV9YDoqjghHeIKUX7Jn '\
- 'KiHL5gk404S5a/Bv'
+
+ pk = 'AwEAAfB9jK8rj/FAdE3t9bYXiTLpelwlgUyxbHEtvMvhdxs+yHv0h9fE '\
+ '710u94LPAeVmXumT6SZPsoo+ALKdmTexkcU9DGQvb2+sPfModBKM/num '\
+ 'rScUw1FBe3HwRa9SqQpgpnCjIt0kEVKHAQdLOP86YznSA9uHAg9TTJuT '\
+ 'LkUtgtmwNAVFr6/mG+smE1v5NbxPccsFwVTA/T1IyaI4Z48VGCP2WNro '\
+ 'R7P6vet1gWhssirnnVYnur8DwWuMJ89o/HjzXeiEGUB8k5SOX+//67FN '\
+ 'm8Zs+1ObuAfY8xAHe0L5bxluEbh1T1ARp41QX77EMKVbkcSj7nuBeY8H '\
+ 'KiN8HsTvmZyDbRAQQaAJi68qOXsUIoQcpn89PoNoc60F7WlueA6ExSGX '\
+ 'KMWIH6nfLXFgidoZ6HxteyUUnZbHEdULjpAoCRuUDjjUnUgFS7eRANfw '\
+ 'RCcu9aLziMDp4UU61zVjtmQ7xn3G2W2+2ycqn/vEl/yFyBmHZ+7stpoC '\
+ 'd6NTZUn4/ellYSm9lx/vaXdPSinARpYMWtU79Hu/VRifaCQjYkBGAMwK '\
+ 'DshX4yJPjza/bqo0XV4WHj1szDFHe0tLN7g1Ojwtf5FR0zyHU3FN9uUa '\
+ 'y8a+dowd/fqOQA1jXR04g2PIfFYe0VudCEpmxSV9YDoqjghHeIKUX7Jn '\
+ 'KiHL5gk404S5a/Bv'
+
+ dk.public_key = pk
+
dk.save
dk.ds_digest.should == 'D7045D3C2EF7332409A132D935C8E2834A2AAB769B35BC370FA68C9445398288'
dk.ds_key_tag.should == '31051'
+
+ dk.public_key.should == pk
end
end
end
diff --git a/spec/models/registrar_spec.rb b/spec/models/registrar_spec.rb
index 7271a307d..4c92e5f66 100644
--- a/spec/models/registrar_spec.rb
+++ b/spec/models/registrar_spec.rb
@@ -28,6 +28,10 @@ describe Registrar do
@registrar.errors[:email].should == ['is invalid']
@registrar.errors[:billing_email].should == ['is invalid']
end
+
+ it 'should not have valid code' do
+ @registrar.code.should == nil
+ end
end
context 'with valid attributes' do
@@ -59,5 +63,26 @@ describe Registrar do
it 'should return full address' do
@registrar.address.should == 'Street 999, Town, County, Postal'
end
+
+ it 'should have code' do
+ @registrar.code.should =~ /registrar/
+ end
+
+ it 'should not be able to change code' do
+ @registrar.code = 'not-updated'
+ @registrar.code.should =~ /registrar/
+ end
+
+ it 'should automatically add next code if original is taken' do
+ @registrar = Fabricate(:registrar, name: 'uniq')
+ @registrar.name = 'New name'
+ @registrar.code.should == 'uniq'
+ @registrar.save
+
+ @new_registrar = Fabricate.build(:registrar, name: 'uniq')
+ @new_registrar.valid?
+ @new_registrar.errors.full_messages.should == []
+ @new_registrar.code.should == 'uniq1'
+ end
end
end
diff --git a/spec/support/epp.rb b/spec/support/epp.rb
index 3bceb034d..35b24a942 100644
--- a/spec/support/epp.rb
+++ b/spec/support/epp.rb
@@ -112,7 +112,7 @@ module Epp
end
def next_domain_name
- "example#{@uniq_no.call}.ee"
+ "example#{rand(100000000)}.ee"
end
### REQUEST TEMPLATES ###
diff --git a/spec/support/epp_contact_xml_helper.rb b/spec/support/epp_contact_xml_helper.rb
deleted file mode 100644
index 693e12ae7..000000000
--- a/spec/support/epp_contact_xml_helper.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-module EppContactXmlHelper
- def create_contact_xml(xml_params = {})
- defaults = {
- postalInfo: {
- name: { value: 'John Doe' },
- addr: {
- street: { value: '123 Example' },
- city: { value: 'Tallinn' },
- cc: { value: 'EE' }
- }
- },
- voice: { value: '+372.1234567' },
- email: { value: 'test@example.example' },
- ident: { value: '37605030299', attrs: { type: 'op' } }
- }
-
- xml_params = defaults.deep_merge(xml_params)
- epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345')
- epp_xml.create(xml_params)
- end
-
- def update_contact_xml(xml_params = {})
- defaults = {
- id: { value: 'asd123123er' },
- authInfo: { pw: { value: 'password' } },
- chg: {
- postalInfo: {
- name: { value: 'John Doe Edited' }
- },
- voice: { value: '+372.7654321' },
- email: { value: 'edited@example.example' },
- disclose: {
- value: {
- voice: { value: '' },
- email: { value: '' }
- }, attrs: { flag: '0' }
- }
- }
- }
- xml_params = defaults.deep_merge(xml_params)
- epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345')
- epp_xml.update(xml_params)
- end
-
- def delete_contact_xml(xml_params = {})
- defaults = { id: { value: 'sh8012' } }
- xml_params = defaults.deep_merge(xml_params)
- epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345')
- epp_xml.delete(xml_params)
- end
-
- def info_contact_xml(xml_params = {})
- defaults = { id: { value: 'sh8012' }, authInfo: { pw: { value: 'password' } } }
- xml_params = defaults.deep_merge(xml_params)
- epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345')
- epp_xml.info(xml_params)
- end
-
- def check_contact_xml(xml_params = {})
- defaults = {
- id: { value: 'ad123c3' }
- }
- xml_params = defaults.deep_merge(xml_params)
- epp_xml = EppXml::Contact.new(cl_trid: 'ABC-12345')
- epp_xml.check(xml_params)
- end
-
- def check_multiple_contacts_xml
- '
-
-
-
-
- check-1234
- check-4321
-
-
- ABC-12345
-
- '
- end
-end
-
-RSpec.configure do |c|
- c.include EppContactXmlHelper
-end