Merge remote-tracking branch 'origin/master' into log-bounced-emails

This commit is contained in:
Karl Erik Õunapuu 2020-10-27 11:34:19 +02:00
commit fc34105c40
No known key found for this signature in database
GPG key ID: C9DD647298A34764
70 changed files with 791 additions and 4967 deletions

View file

@ -1,3 +1,46 @@
20.10.2020
* ForceDelete mailer now respects option to not notify registrant [#1719](https://github.com/internetee/registry/pull/1719)
19.10.2020
* Improved logging for LHV-connect messages [#1712](https://github.com/internetee/registry/issues/1712)
* LHV-connect gem update to handle blank descriptions [#1714](https://github.com/internetee/registry/issues/1714)
16.10.2020
* Improved error handling for registrant API comapnies endpoint [#1713](https://github.com/internetee/registry/pull/1713)
15.10.2020
* Tara integration for registrant portal [#1698](https://github.com/internetee/registry/pull/1698)
14.10.2020
* Added company registration data query to regisrant API [#1708](https://github.com/internetee/registry/issues/1708)
* Fixed domain delete history records in admin [#1710](https://github.com/internetee/registry/issues/1710)
09.10.2020
* Fixed pendingUpdate release while forceDelete is set [#1705](https://github.com/internetee/registry/issues/1705)
08.10.2020
* Fixed serach in admin history [#1695](https://github.com/internetee/registry/issues/1695)
06.10.2020
* Updated Directo gem to fix vat codes for EU and non-EU clients [#1699](https://github.com/internetee/registry/pull/1699)
* Email validation level is now configurable [#1675](https://github.com/internetee/registry/pull/1675)
01.10.2020
* Fixed EPP authentication [#1697](https://github.com/internetee/registry/pull/1697)
30.09.2020
* Added Tara integration to registrar portal [#1680](https://github.com/internetee/registry/issues/1680)
28.09.2020
* Fixed data leakage with shared contacts [#1690](https://github.com/internetee/registry/issues/1690)
* RenewProhoboted status blocks renew [#1693](https://github.com/internetee/registry/issues/1693)
18.09.2020
* Updated testing documentation [#1285](https://github.com/internetee/registry/pull/1285)
* Removed mod-epp docs - replaced by epp-proxy [#1284](https://github.com/internetee/registry/pull/1284)
* Removed outdated diagrams [#1073](https://github.com/internetee/registry/pull/1073)
* Removed unused autodoc gems [#1358](https://github.com/internetee/registry/pull/1358)
16.09.2020
* Refactored orphaned contact archivation process [#956](https://github.com/internetee/registry/issues/956)
* Rails update to 6.0.3.3 [#1685](https://github.com/internetee/registry/pull/1685)

11
Gemfile
View file

@ -53,6 +53,11 @@ gem 'digidoc_client',
github: 'tarmotalu/digidoc_client',
ref: '1645e83a5a548addce383f75703b0275c5310c32'
# TARA
gem 'omniauth'
gem 'omniauth-rails_csrf_protection'
gem 'omniauth-tara', github: 'internetee/omniauth-tara'
gem 'epp', github: 'internetee/epp', branch: :master
gem 'epp-xml', '1.1.0', github: 'internetee/epp-xml'
@ -63,7 +68,8 @@ gem 'pdfkit'
gem 'jquery-ui-rails', '5.0.5'
gem 'airbrake'
gem 'company_register', github: 'internetee/company_register', branch: :master
gem 'company_register', github: 'internetee/company_register',
branch: 'master'
gem 'e_invoice', github: 'internetee/e_invoice', branch: :master
gem 'lhv', github: 'internetee/lhv', branch: 'master'
gem 'domain_name'
@ -80,10 +86,7 @@ end
group :development, :test do
gem 'pry', '0.10.1'
gem 'railroady', '1.3.0' # to generate database diagrams
gem 'autodoc'
gem 'puma'
gem 'sdoc', '~> 1.1'
end
group :test do

View file

@ -1,6 +1,6 @@
GIT
remote: https://github.com/internetee/company_register.git
revision: 86d691997aa7def9f86d88f6c92cabb86cd65487
revision: 4181b2fff9080e2d87d15612561131f9e3fdfb4c
branch: master
specs:
company_register (0.1.0)
@ -9,7 +9,7 @@ GIT
GIT
remote: https://github.com/internetee/directo.git
revision: e4ba54f601d1815fd8782a196788730d47861e86
revision: 711ce2d942456ee830b649b03b7141e903a1d86b
branch: master
specs:
directo (1.0.1)
@ -45,13 +45,22 @@ GIT
GIT
remote: https://github.com/internetee/lhv.git
revision: 1825240b3bf8b262418cc6c8ef7ed1aba386dd7d
revision: 1fb07818369425510a0172ad53bc86e85b6f83cc
branch: master
specs:
lhv (0.1.0)
logger
nokogiri
GIT
remote: https://github.com/internetee/omniauth-tara.git
revision: cec845ec3794532144c4976104a07e206d759aa6
specs:
omniauth-tara (0.3.0)
addressable (~> 2.5)
omniauth (~> 1.3)
openid_connect (~> 1.1)
GIT
remote: https://github.com/tarmotalu/digidoc_client.git
revision: 1645e83a5a548addce383f75703b0275c5310c32
@ -111,7 +120,7 @@ GEM
activerecord (6.0.3.3)
activemodel (= 6.0.3.3)
activesupport (= 6.0.3.3)
activerecord-import (1.0.5)
activerecord-import (1.0.6)
activerecord (>= 3.2)
activestorage (6.0.3.3)
actionpack (= 6.0.3.3)
@ -126,21 +135,20 @@ GEM
zeitwerk (~> 2.2, >= 2.2.2)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
airbrake (10.0.5)
airbrake-ruby (~> 4.13)
airbrake-ruby (4.15.0)
aes_key_wrap (1.1.0)
airbrake (11.0.0)
airbrake-ruby (~> 5.0)
airbrake-ruby (5.0.2)
rbtree3 (~> 0.5)
akami (1.3.1)
gyoku (>= 0.4.0)
nokogiri
autodoc (0.7.4)
actionpack
activesupport (>= 3.0.0)
rspec
autoprefixer-rails (9.8.4)
attr_required (1.0.1)
autoprefixer-rails (10.0.0.2)
execjs
bcrypt (3.1.13)
bootsnap (1.4.6)
bcrypt (3.1.16)
bindata (2.4.8)
bootsnap (1.4.8)
msgpack (~> 1.0)
bootstrap-sass (3.4.1)
autoprefixer-rails (>= 5.2.1)
@ -170,8 +178,7 @@ GEM
i18n_data (~> 0.10.0)
sixarm_ruby_unaccent (~> 1.1)
unicode_utils (~> 1.4)
crack (0.4.3)
safe_yaml (~> 1.0.0)
crack (0.4.4)
crass (1.0.6)
daemons (1.3.1)
daemons-rails (1.2.1)
@ -180,13 +187,12 @@ GEM
data_migrate (6.3.0)
rails (>= 5.0)
database_cleaner (1.8.5)
devise (4.7.2)
devise (4.7.3)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
diff-lcs (1.4.4)
docile (1.3.2)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
@ -201,7 +207,7 @@ GEM
concurrent-ruby (~> 1.0)
dry-equalizer (0.3.0)
dry-inflector (0.2.0)
dry-logic (1.0.6)
dry-logic (1.0.7)
concurrent-ruby (~> 1.0)
dry-core (~> 0.2)
dry-equalizer (~> 0.2)
@ -220,7 +226,7 @@ GEM
thor (~> 0.14)
globalid (0.4.2)
activesupport (>= 4.2.0)
grape (1.3.3)
grape (1.4.0)
activesupport
builder
dry-types (>= 1.1)
@ -233,6 +239,7 @@ GEM
temple (>= 0.8.0)
tilt
hashdiff (1.0.1)
hashie (4.1.0)
hpricot (0.8.6)
http-accept (1.7.0)
http-cookie (1.0.3)
@ -253,6 +260,10 @@ GEM
jquery-ui-rails (5.0.5)
railties (>= 3.2.16)
json (2.3.1)
json-jwt (1.13.0)
activesupport (>= 4.2)
aes_key_wrap
bindata
kaminari (1.2.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.1)
@ -298,7 +309,7 @@ GEM
money (~> 6.13.2)
railties (>= 3.0)
msgpack (1.3.3)
multi_json (1.14.1)
multi_json (1.15.0)
mustermann (1.1.1)
ruby2_keywords (~> 0.0.1)
mustermann-grape (1.0.1)
@ -308,12 +319,28 @@ GEM
nokogiri (1.10.10)
mini_portile2 (~> 2.4.0)
nori (2.6.0)
omniauth (1.9.1)
hashie (>= 3.4.6)
rack (>= 1.6.2, < 3)
omniauth-rails_csrf_protection (0.1.2)
actionpack (>= 4.2)
omniauth (>= 1.3.1)
open4 (1.3.4)
openid_connect (1.2.0)
activemodel
attr_required (>= 1.0.0)
json-jwt (>= 1.5.0)
rack-oauth2 (>= 1.6.1)
swd (>= 1.0.0)
tzinfo
validate_email
validate_url
webfinger (>= 1.0.1)
orm_adapter (0.5.0)
paper_trail (10.3.1)
activerecord (>= 4.2)
request_store (~> 1.1)
pdfkit (0.8.4.3.1)
pdfkit (0.8.4.3.2)
pg (1.2.2)
polyamorous (2.3.2)
activerecord (>= 5.2.1)
@ -322,7 +349,7 @@ GEM
method_source (~> 0.8.1)
slop (~> 3.4)
public_suffix (4.0.6)
puma (4.3.5)
puma (5.0.0)
nio4r (~> 2.0)
que (0.14.3)
que-web (0.7.2)
@ -332,11 +359,16 @@ GEM
rack (2.2.3)
rack-accept (0.4.5)
rack (>= 0.4)
rack-protection (2.0.8.1)
rack-oauth2 (1.16.0)
activesupport
attr_required
httpclient
json-jwt (>= 1.11.0)
rack (>= 2.1.0)
rack-protection (2.1.0)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
railroady (1.3.0)
rails (6.0.3.3)
actioncable (= 6.0.3.3)
actionmailbox (= 6.0.3.3)
@ -373,8 +405,7 @@ GEM
rb-inotify (0.10.1)
ffi (~> 1.0)
rbtree3 (0.6.0)
rdoc (6.2.1)
regexp_parser (1.7.1)
regexp_parser (1.8.0)
request_store (1.5.0)
rack (>= 1.4)
responders (3.0.1)
@ -385,22 +416,8 @@ GEM
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
rspec (3.9.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-core (3.9.2)
rspec-support (~> 3.9.3)
rspec-expectations (3.9.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-mocks (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-support (3.9.3)
ruby2_keywords (0.0.2)
rubyzip (2.3.0)
safe_yaml (1.0.5)
sass-rails (6.0.0)
sassc-rails (~> 2.1, >= 2.1.1)
sassc (2.4.0)
@ -419,8 +436,6 @@ GEM
nokogiri (>= 1.8.1)
nori (~> 2.4)
wasabi (~> 3.4)
sdoc (1.1.0)
rdoc (>= 5.0)
select2-rails (3.5.9.3)
thor (~> 0.14)
selectize-rails (0.12.1)
@ -434,10 +449,10 @@ GEM
simplecov-html (0.10.2)
simpleidn (0.1.1)
unf (~> 0.1.4)
sinatra (2.0.8.1)
sinatra (2.1.0)
mustermann (~> 1.0)
rack (~> 2.0)
rack-protection (= 2.0.8.1)
rack (~> 2.2)
rack-protection (= 2.1.0)
tilt (~> 2.0)
sixarm_ruby_unaccent (1.2.0)
slop (3.6.0)
@ -449,11 +464,15 @@ GEM
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
swd (1.2.0)
activesupport (>= 3)
attr_required (>= 0.0.5)
httpclient (>= 2.4)
temple (0.8.2)
thor (0.20.3)
thread_safe (0.3.6)
tilt (2.0.10)
truemail (1.8.0)
truemail (1.9.1)
simpleidn (~> 0.1.1)
tzinfo (1.2.7)
thread_safe (~> 0.1)
@ -463,10 +482,16 @@ GEM
unf_ext
unf_ext (0.0.7.7)
unicode_utils (1.4.0)
validate_email (0.1.6)
activemodel (>= 3.0)
mail (>= 2.2.5)
validate_url (1.0.13)
activemodel (>= 3.0.0)
public_suffix
validates_email_format_of (1.6.3)
i18n
warden (1.2.8)
rack (>= 2.0.6)
warden (1.2.9)
rack (>= 2.0.9)
wasabi (3.6.1)
addressable
httpi (~> 2.0)
@ -475,7 +500,10 @@ GEM
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (>= 3.0, < 4.0)
webmock (3.8.3)
webfinger (1.1.0)
activesupport
httpclient (>= 2.4)
webmock (3.9.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
@ -495,7 +523,6 @@ PLATFORMS
DEPENDENCIES
activerecord-import
airbrake
autodoc
bootsnap (>= 1.1.0)
bootstrap-sass (~> 3.4)
cancancan
@ -528,6 +555,9 @@ DEPENDENCIES
minitest (~> 5.14)
money-rails
nokogiri
omniauth
omniauth-rails_csrf_protection
omniauth-tara!
paper_trail (~> 10.3)
pdfkit
pg (= 1.2.2)
@ -535,12 +565,10 @@ DEPENDENCIES
puma
que
que-web
railroady (= 1.3.0)
rails (~> 6.0)
ransack (~> 2.3)
rest-client
sass-rails
sdoc (~> 1.1)
select2-rails (= 3.5.9.3)
selectize-rails (= 0.12.1)
simplecov (= 0.17.1)

View file

@ -17,15 +17,8 @@ Documentation
-------------
* [EPP documentation](/doc/epp)
* [EPP request-response examples](/doc/epp_examples.md)
* [REPP documentation](/doc/repp_doc.md)
* [Database diagram](/doc/models_complete.svg)
* [Controllers diagram](/doc/controllers_complete.svg)
### Updating documentation
AUTODOC=true rspec spec/requests
EPP_DOC=true rspec spec/epp --tag epp --require support/epp_doc.rb --format EppDoc > doc/epp_examples.md
* [EPP request-response examples](/doc/epp-examples.md)
* [REPP documentation](/doc/repp-doc.md)
Installation
------------
@ -47,24 +40,10 @@ Manual demo install and database setup:
bundle exec rake bootstrap
bundle exec rake assets:precompile
### Apache with patched mod_epp (Debian 7/Ubuntu 14.04 LTS)
### Apache (Debian 7/Ubuntu 14.04 LTS)
sudo apt-get install apache2
sudo apt-get install apache2-threaded-dev # needed to compile mod_epp
wget sourceforge.net/projects/aepps/files/mod_epp/1.10/mod_epp-1.10.tar.gz
tar -xzvf mod_epp-1.10.tar.gz
cd mod_epp-1.10
Patch mod_epp for Rack. Beacause Rack multipart parser expects specifically
formatted content boundaries, the mod_epp needs to be modified before building:
wget https://github.com/internetee/registry/raw/master/doc/patches/mod_epp_1.10-rack-friendly.patch
wget https://raw.githubusercontent.com/domify/registry/master/doc/patches/mod_epp_1.10-frame-size.patch
patch < mod_epp_1.10-rack-friendly.patch
patch < mod_epp_1.10-frame-size.patch
sudo apxs2 -a -c -i mod_epp.c
Enable ssl:
sudo a2enmod proxy_http
@ -380,37 +359,6 @@ Be sure to update paths to match your system configuration.
</Directory>
</VirtualHost>
</IfModule>
<IfModule mod_epp.c>
Listen 700
<VirtualHost *:700>
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 require
SSLVerifyDepth 1
SSLCACertificateFile /home/registry/registry/shared/ca/certs/ca.crt.pem
SSLCARevocationPath /home/registry/registry/shared/ca/crl
# Uncomment this when upgrading to apache 2.4:
# SSLCARevocationCheck chain
RequestHeader set SSL_CLIENT_S_DN_CN "%{SSL_CLIENT_S_DN_CN}s"
RequestHeader set SSL_CLIENT_CERT "%{SSL_CLIENT_CERT}s"
EPPEngine On
EPPCommandRoot /proxy/command
EPPSessionRoot /proxy/session
EPPErrorRoot /proxy/error
EPPRawFrame raw_frame
ProxyPass /proxy/ http://localhost:8080/epp/
EPPAuthURI implicit
EPPReturncodeHeader X-EPP-Returncode
</VirtualHost>
</IfModule>
```
Enable epp_ssl and restart apache
@ -426,6 +374,8 @@ All registry demo data can be found at:
Initially you can use two type of users: admin users and EPP users.
For using EPP we are strongly recommend to install epp_proxy instead of mod_epp. You can get epp_proxy from https://github.com/internetee/epp_proxy
### Wkhtmltopdf setup
```

View file

@ -0,0 +1,52 @@
require 'serializers/registrant_api/company'
module Api
module V1
module Registrant
class CompaniesController < ::Api::V1::Registrant::BaseController
MAX_LIMIT = 200
MIN_OFFSET = 0
def index
result = error_result('limit') if limit > MAX_LIMIT || limit < 1
result = error_result('offset') if offset < MIN_OFFSET
result ||= companies_result(limit, offset)
render result
end
def current_user_companies
[:ok, current_registrant_user.companies]
rescue CompanyRegister::NotAvailableError
[:service_unavailable, []]
end
def limit
(params[:limit] || MAX_LIMIT).to_i
end
def offset
(params[:offset] || MIN_OFFSET).to_i
end
def error_result(attr_name)
{ json: { errors: [{ attr_name.to_sym => ['parameter is out of range'] }] },
status: :bad_request }
end
def companies_result(limit, offset)
status, all_companies = current_user_companies
@companies = all_companies.drop(offset).first(limit)
serialized_companies = @companies.map do |item|
country_code = current_registrant_user.country.alpha3
serializer = ::Serializers::RegistrantApi::Company.new(company: item,
country_code: country_code)
serializer.to_json
end
{ json: { companies: serialized_companies }, status: status }
end
end
end
end
end

View file

@ -91,7 +91,7 @@ module Api
private
def current_user_contacts
current_registrant_user.contacts
current_registrant_user.contacts(representable: false)
rescue CompanyRegister::NotAvailableError
current_registrant_user.direct_contacts
end

View file

@ -343,7 +343,9 @@ module Epp
end
def epp_session_id
cookies[:session] # Passed by mod_epp https://github.com/mod-epp/mod-epp#requestscript-interface
# Passed by EPP proxy
# https://github.com/internetee/epp_proxy#translation-of-epp-calls
cookies[:session]
end
def ensure_session_id_passed

View file

@ -1,81 +1,6 @@
class Registrant::SessionsController < Devise::SessionsController
layout 'registrant/application'
def login_mid
@user = User.new
end
def mid
phone = params[:user][:phone]
endpoint = "#{ENV['sk_digi_doc_service_endpoint']}"
client = Digidoc::Client.new(endpoint)
client.logger = Rails.application.config.logger unless Rails.env.test?
# country_codes = {'+372' => 'EST'}
response = client.authenticate(
phone: "+372#{phone}",
message_to_display: 'Authenticating',
service_name: ENV['sk_digi_doc_service_name'] || 'Testing'
)
if response.faultcode
render json: { message: response.detail.message }, status: :unauthorized
return
end
@user = RegistrantUser.find_or_create_by_mid_data(response)
if @user.persisted?
session[:user_country] = response.user_country
session[:user_id_code] = response.user_id_code
session[:mid_session_code] = client.session_code
render json: {
message: t(:confirmation_sms_was_sent_to_your_phone_verification_code_is, { code: response.challenge_id })
}, status: :ok
else
render json: { message: t(:no_such_user) }, status: :unauthorized
end
end
def mid_status
endpoint = "#{ENV['sk_digi_doc_service_endpoint']}"
client = Digidoc::Client.new(endpoint)
client.logger = Rails.application.config.logger unless Rails.env.test?
client.session_code = session[:mid_session_code]
auth_status = client.authentication_status
case auth_status.status
when 'OUTSTANDING_TRANSACTION'
render json: { message: t(:check_your_phone_for_confirmation_code) }, status: :ok
when 'USER_AUTHENTICATED'
@user = RegistrantUser.find_by(registrant_ident: "#{session[:user_country]}-#{session[:user_id_code]}")
sign_in(:registrant_user, @user)
flash[:notice] = t(:welcome)
flash.keep(:notice)
render js: "window.location = '#{registrant_root_path}'"
when 'NOT_VALID'
render json: { message: t(:user_signature_is_invalid) }, status: :bad_request
when 'EXPIRED_TRANSACTION'
render json: { message: t(:session_timeout) }, status: :bad_request
when 'USER_CANCEL'
render json: { message: t(:user_cancelled) }, status: :bad_request
when 'MID_NOT_READY'
render json: { message: t(:mid_not_ready) }, status: :bad_request
when 'PHONE_ABSENT'
render json: { message: t(:phone_absent) }, status: :bad_request
when 'SENDING_ERROR'
render json: { message: t(:sending_error) }, status: :bad_request
when 'SIM_ERROR'
render json: { message: t(:sim_error) }, status: :bad_request
when 'INTERNAL_ERROR'
render json: { message: t(:internal_error) }, status: :bad_request
else
render json: { message: t(:internal_error) }, status: :bad_request
end
end
private
def after_sign_in_path_for(_resource_or_scope)

View file

@ -49,102 +49,6 @@ class Registrar
end
end
def id_card
self.resource = warden.authenticate!(auth_options)
restricted_ip = Authorization::RestrictedIP.new(request.ip)
ip_allowed = restricted_ip.can_access_registrar_area?(resource.registrar)
unless ip_allowed
render plain: t('registrar.authorization.ip_not_allowed', ip: request.ip)
warden.logout(:registrar_user)
return
end
set_flash_message!(:notice, :signed_in)
sign_in(resource_name, resource)
yield resource if block_given?
respond_with resource, location: after_sign_in_path_for(resource)
end
def login_mid
@user = User.new
end
def mid
phone = params[:user][:phone]
endpoint = "#{ENV['sk_digi_doc_service_endpoint']}"
client = Digidoc::Client.new(endpoint)
client.logger = Rails.application.config.logger unless Rails.env.test?
# country_codes = {'+372' => 'EST'}
phone.gsub!('+372', '')
response = client.authenticate(
phone: "+372#{phone}",
message_to_display: 'Authenticating',
service_name: ENV['sk_digi_doc_service_name'] || 'Testing'
)
if response.faultcode
render json: { message: response.detail.message }, status: :unauthorized
return
end
if Setting.registrar_ip_whitelist_enabled
@user = find_user_by_idc_and_allowed(response.user_id_code)
else
@user = find_user_by_idc(response.user_id_code)
end
if @user.persisted?
session[:user_id_code] = response.user_id_code
session[:mid_session_code] = client.session_code
render json: {
message: t(:confirmation_sms_was_sent_to_your_phone_verification_code_is, { code: response.challenge_id })
}, status: :ok
else
render json: { message: t(:no_such_user) }, status: :unauthorized
end
end
def mid_status
endpoint = "#{ENV['sk_digi_doc_service_endpoint']}"
client = Digidoc::Client.new(endpoint)
client.logger = Rails.application.config.logger unless Rails.env.test?
client.session_code = session[:mid_session_code]
auth_status = client.authentication_status
case auth_status.status
when 'OUTSTANDING_TRANSACTION'
render json: { message: t(:check_your_phone_for_confirmation_code) }, status: :ok
when 'USER_AUTHENTICATED'
@user = find_user_by_idc_and_allowed(session[:user_id_code])
sign_in(:registrar_user, @user)
flash[:notice] = t(:welcome)
flash.keep(:notice)
render js: "window.location = '#{after_sign_in_path_for(@user)}'"
when 'NOT_VALID'
render json: { message: t(:user_signature_is_invalid) }, status: :bad_request
when 'EXPIRED_TRANSACTION'
render json: { message: t(:session_timeout) }, status: :bad_request
when 'USER_CANCEL'
render json: { message: t(:user_cancelled) }, status: :bad_request
when 'MID_NOT_READY'
render json: { message: t(:mid_not_ready) }, status: :bad_request
when 'PHONE_ABSENT'
render json: { message: t(:phone_absent) }, status: :bad_request
when 'SENDING_ERROR'
render json: { message: t(:sending_error) }, status: :bad_request
when 'SIM_ERROR'
render json: { message: t(:sim_error) }, status: :bad_request
when 'INTERNAL_ERROR'
render json: { message: t(:internal_error) }, status: :bad_request
else
render json: { message: t(:internal_error) }, status: :bad_request
end
end
private
def depp_controller?

View file

@ -0,0 +1,40 @@
module Sso
class TaraController < ApplicationController
skip_authorization_check
def registrant_callback
user = RegistrantUser.find_or_create_by_omniauth_data(user_hash)
callback(user, registrar: false)
end
def registrar_callback
user = ApiUser.from_omniauth(user_hash)
callback(user, registrar: true)
end
# rubocop:disable Style/AndOr
def callback(user, registrar: true)
session[:omniauth_hash] = user_hash
(show_error(registrar: registrar) and return) unless user
flash[:notice] = t(:signed_in_successfully)
sign_in_and_redirect(registrar ? :registrar_user : :registrant_user, user)
end
# rubocop:enable Style/AndOr
def cancel
redirect_to root_path, notice: t(:sign_in_cancelled)
end
def show_error(registrar: true)
path = registrar ? new_registrar_user_session_url : new_registrant_user_session_url
redirect_to path, alert: t(:no_such_user)
end
private
def user_hash
request.env['omniauth.auth']
end
end
end

View file

@ -2,7 +2,7 @@ require 'open3'
class ApiUser < User
include EppErrors
devise :database_authenticatable, :trackable, :timeoutable, :id_card_authenticatable,
devise :database_authenticatable, :trackable, :timeoutable,
authentication_keys: [:username]
def epp_code_map
@ -47,12 +47,6 @@ class ApiUser < User
self.active = true unless saved_change_to_active?
end
class << self
def find_by_id_card(id_card)
find_by(identity_code: id_card.personal_code)
end
end
def to_s
username
end

View file

@ -15,7 +15,7 @@ module Concerns
domain.registrar.notifications.create!(text: I18n.t('grace_period_started_domain',
domain_name: domain.name,
date: domain.force_delete_start))
send_mail(domain)
send_mail(domain) if domain.template_name.present?
domain.update(contact_notification_sent_date: Time.zone.today)
end

View file

@ -210,10 +210,13 @@ class Contact < ApplicationRecord
)
end
def registrant_user_contacts(registrant_user)
registrant_user_direct_contacts(registrant_user)
.or(registrant_user_company_contacts(registrant_user))
.or(registrant_user_indirect_contacts(registrant_user))
def registrant_user_contacts(registrant_user, representable: true)
represented_contacts = registrant_user_direct_contacts(registrant_user)
.or(registrant_user_company_contacts(registrant_user))
return represented_contacts if representable
represented_contacts.or(registrant_user_indirect_contacts(registrant_user))
end
def registrant_user_direct_contacts(registrant_user)

View file

@ -306,11 +306,7 @@ class Domain < ApplicationRecord
end
def renewable?
blocking_statuses = [DomainStatus::DELETE_CANDIDATE, DomainStatus::PENDING_RENEW,
DomainStatus::PENDING_TRANSFER, DomainStatus::DISPUTED,
DomainStatus::PENDING_UPDATE, DomainStatus::PENDING_DELETE,
DomainStatus::PENDING_DELETE_CONFIRMATION]
return false if statuses.include_any? blocking_statuses
return false unless renew_blocking_statuses.empty?
return true unless Setting.days_to_renew_domain_before_expire != 0
# if you can renew domain at days_to_renew before domain expiration
@ -321,6 +317,15 @@ class Domain < ApplicationRecord
true
end
def renew_blocking_statuses
disallowed = [DomainStatus::DELETE_CANDIDATE, DomainStatus::PENDING_RENEW,
DomainStatus::PENDING_TRANSFER, DomainStatus::CLIENT_RENEW_PROHIBITED,
DomainStatus::PENDING_UPDATE, DomainStatus::PENDING_DELETE,
DomainStatus::PENDING_DELETE_CONFIRMATION, DomainStatus::SERVER_RENEW_PROHIBITED]
(statuses & disallowed)
end
def notify_registrar(message_key)
registrar.notifications.create!(
text: "#{I18n.t(message_key)}: #{name}",
@ -484,7 +489,7 @@ class Domain < ApplicationRecord
end
def pending_update?
statuses.include?(DomainStatus::PENDING_UPDATE) && !statuses.include?(DomainStatus::FORCE_DELETE)
statuses.include?(DomainStatus::PENDING_UPDATE)
end
# depricated not used, not valid

View file

@ -581,11 +581,14 @@ class Epp::Domain < Domain
save(validate: false)
end
### RENEW ###
def renew(cur_exp_date, period, unit = 'y')
@is_renewal = true
validate_exp_dates(cur_exp_date)
add_epp_error('2105', nil, nil, I18n.t('object_is_not_eligible_for_renewal')) unless renewable?
add_renew_epp_errors unless renewable?
return false if errors.any?
period = period.to_i
@ -613,6 +616,13 @@ class Epp::Domain < Domain
save
end
def add_renew_epp_errors
if renew_blocking_statuses.any? && !renewable?
add_epp_error('2304', 'status', renew_blocking_statuses,
I18n.t('object_status_prohibits_operation'))
end
end
### TRANSFER ###
def transfer(frame, action, current_user)

View file

@ -1,6 +0,0 @@
class IdCard
attr_accessor :first_name
attr_accessor :last_name
attr_accessor :personal_code
attr_accessor :country_code
end

View file

@ -1,7 +1,7 @@
class RegistrantUser < User
attr_accessor :idc_data
devise :trackable, :timeoutable, :id_card_authenticatable
devise :trackable, :timeoutable
def ability
@ability ||= Ability.new(self)
@ -22,8 +22,8 @@ class RegistrantUser < User
citizen_country_code: country.alpha3)
end
def contacts
Contact.registrant_user_contacts(self)
def contacts(representable: true)
Contact.registrant_user_contacts(self, representable: representable)
end
def direct_contacts
@ -66,23 +66,19 @@ class RegistrantUser < User
find_or_create_by_user_data(user_data)
end
def find_or_create_by_mid_data(response)
user_data = { first_name: response.user_givenname, last_name: response.user_surname,
ident: response.user_id_code, country_code: response.user_country }
def find_or_create_by_omniauth_data(omniauth_hash)
uid = omniauth_hash['uid']
identity_code = uid.slice(2..-1)
country_code = uid.slice(0..1)
first_name = omniauth_hash.dig('info', 'first_name')
last_name = omniauth_hash.dig('info', 'last_name')
user_data = { first_name: first_name, last_name: last_name,
ident: identity_code, country_code: country_code }
find_or_create_by_user_data(user_data)
end
def find_by_id_card(id_card)
registrant_ident = "#{id_card.country_code}-#{id_card.personal_code}"
username = [id_card.first_name, id_card.last_name].join("\s")
user = find_or_initialize_by(registrant_ident: registrant_ident)
user.username = username
user.save!
user
end
private
def find_or_create_by_user_data(user_data = {})

View file

@ -11,4 +11,11 @@ class User < ApplicationRecord
"#{self.id}-#{self.class}: #{self.username}"
end
def self.from_omniauth(omniauth_hash)
uid = omniauth_hash['uid']
identity_code = uid.slice(2..-1)
# country_code = uid.slice(0..1)
find_by(identity_code: identity_code)
end
end

View file

@ -57,7 +57,7 @@
- if version
- attributes = only_present_fields(version, Domain)
- domain = Domain.new(attributes)
- attach_existing_fields(version, domain)
- attach_existing_fields(version, domain) unless version.event == 'destroy'
%tr
%td= link_to(domain.name, admin_domain_version_path(version.id))
@ -67,7 +67,7 @@
- else
- contact = Contact.all_versions_for([domain.registrant_id], version.created_at).first
- if contact.nil? && ver = ContactVersion.where(item_id: domain.registrant_id).last
- contact = Contact.new(ver.object.to_h.merge(ver.object_changes.to_h.each_with_object({}){|(k,v), o| o.public_send("#{k}=", v.last) } ))
- contact = Contact.new(ver.object.to_h.merge(ver.object_changes.to_h.each_with_object({}) {|(k,v), o| o[k] = v.last }))
= contact.try(:name)
= "&#160;".html_safe
= "(#{t(:deleted)})"

View file

@ -1,6 +1,6 @@
- present_fields = only_present_fields(@version, Domain)
- domain = Domain.new(present_fields)
- attach_existing_fields(@version, domain)
- attach_existing_fields(@version, domain) unless @version.event == 'destroy'
- if @version
- children = HashWithIndifferentAccess.new(@version.children)

View file

@ -1,40 +0,0 @@
.row
.form-signin.col-md-4.center-block.text-center
%h2.form-signin-heading.text-center= t '.header'
%hr
= form_for @user, url: registrant_mid_path, html: {class: 'form-signin'} do |f|
= f.text_field :phone, class: 'form-control',
placeholder: t(:phone_no), autocomplete: 'off', required: true
%button.btn.btn-lg.btn-primary.btn-block.js-login{:type => 'submit'}= t '.submit_btn'
- if ['development', 'alpha'].include?(Rails.env)
%div.text-center
00007, 60000007, 00000766
:coffee
load_listener = ->
$('.js-login').attr('disabled', false)
status_interval = null
mid_status = () ->
status_interval = setInterval((->
$.post('/registrant/login/mid_status').fail((data) ->
clearInterval(status_interval)
flash_alert(data.responseJSON.message)
$('.js-login').attr('disabled', false)
)
), 1000)
$('.js-login').on 'click', (e) ->
e.preventDefault();
$(this).attr('disabled', true)
$.post($('form').attr('action'), $('form').serialize()).done((data) ->
if data.message
flash_notice(data.message)
mid_status()
).fail((data) ->
flash_alert(data.responseJSON.message)
$('.js-login').attr('disabled', false)
)
window.addEventListener 'load', load_listener

View file

@ -8,11 +8,6 @@
<%= t '.hint' %>
</div>
<br/>
<%= link_to '/registrant/login/mid' do %>
<%= image_tag 'mid.gif' %>
<% end %>
<%= link_to registrant_id_card_sign_in_path, method: :post do %>
<%= image_tag 'id_card.gif' %>
<% end %>
<%= link_to t(:sign_in), "/auth/rant_tara", method: :post, class: 'btn btn-lg btn-primary btn-block' %>
</div>
</div>
</div>

View file

@ -1,40 +0,0 @@
.row
.form-signin.col-md-4.center-block.text-center
%h2.form-signin-heading.text-center= t '.header'
%hr
= form_for @user, url: registrar_mid_path, html: {class: 'form-signin'} do |f|
= f.text_field :phone, class: 'form-control',
placeholder: t(:phone_no), autocomplete: 'off', required: true
%button.btn.btn-lg.btn-primary.btn-block.js-login{:type => 'submit'}= t '.submit_btn'
- if ['development', 'alpha'].include?(Rails.env)
%div.text-center
00007, 60000007, 00000766
:coffee
load_listener = ->
$('.js-login').attr('disabled', false)
status_interval = null
mid_status = () ->
status_interval = setInterval((->
$.post('/registrar/login/mid_status').fail((data) ->
clearInterval(status_interval)
flash_alert(data.responseJSON.message)
$('.js-login').attr('disabled', false)
)
), 1000)
$('.js-login').on 'click', (e) ->
e.preventDefault();
$(this).attr('disabled', true)
$.post($('form').attr('action'), $('form').serialize()).done((data) ->
if data.message
flash_notice(data.message)
mid_status()
).fail((data) ->
flash_alert(data.responseJSON.message)
$('.js-login').attr('disabled', false)
)
window.addEventListener 'load', load_listener

View file

@ -19,12 +19,10 @@
<hr>
<%= link_to '/registrar/login/mid', id: 'login-with-mobile-id-btn' do %>
<%= image_tag 'mid.gif' %>
<% end %>
<%= link_to registrar_id_card_sign_in_path, method: :post do %>
<%= image_tag 'id_card.gif' %>
<% end %>
<div id="tara-sign-in" class="login-block ui segment">
<h3><%= t('.sign_in_with_identity_document') %></h3>
<p><%= t('.identity_document_text')%></p>
<%= link_to t(:sign_in), "/auth/tara", method: :post, class: 'btn btn-lg btn-primary btn-block' %>
</div>
</div>
</div>
</div>

View file

@ -159,6 +159,20 @@ lhv_dev_mode: 'false'
epp_session_timeout_seconds: '300'
contact_archivation_log_file_dir:
tara_host: 'tara-test.ria.ee'
tara_issuer: 'https://tara-test.ria.ee'
tara_identifier: 'identifier'
tara_secret: 'secret'
tara_redirect_uri: 'redirect_url'
tara_keys: "{\"kty\":\"RSA\",\"kid\":\"de6cc4\",\"n\":\"jWwAjT_03ypme9ZWeSe7c-jY26NO50Wo5I1LBnPW2JLc0dPMj8v7y4ehiRpClYNTaSWcLd4DJmlKXDXXudEUWwXa7TtjBFJfzlZ-1u0tDvJ-H9zv9MzO7UhUFytztUEMTrtStdhGbzkzdEZZCgFYeo2i33eXxzIR1nGvI05d9Y-e_LHnNE2ZKTa89BC7ZiCXq5nfAaCgQna_knh4kFAX-KgiPRAtsiDHcAWKcBY3qUVcb-5XAX8p668MlGLukzsh5tFkQCbJVyNtmlbIHdbGvVHPb8C0H3oLYciv1Fjy_tS1lO7OT_cb3GVp6Ql-CG0uED_8pkpVtfsGRviub4_ElQ\",\"e\":\"AQAB\"}"
tara_rant_identifier: 'identifier'
tara_rant_secret: 'secret'
tara_rant_redirect_uri: 'redirect_uri'
default_email_validation_type: 'regex'
# Since the keys for staging are absent from the repo, we need to supply them separate for testing.
test:
payments_seb_bank_certificate: 'test/fixtures/files/seb_bank_cert.pem'

View file

@ -43,7 +43,7 @@ Rails.application.configure do
# config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
config.force_ssl = false
# Use the lowest log level to ensure availability of diagnostic information
# when problems arise.

View file

@ -9,7 +9,7 @@ Devise.setup do |config|
# Devise will use the `secret_key_base` as its `secret_key`
# by default. You can change it below and use your own secret key.
config.secret_key = ENV['devise_secret']
# ==> Controller configuration
# Configure the parent class to the devise controllers.
# config.parent_controller = 'DeviseController'
@ -280,10 +280,4 @@ Devise.setup do |config|
# When using OmniAuth, Devise cannot automatically set OmniAuth path,
# so you need to do it manually. For the users scope, it would be:
# config.omniauth_path_prefix = '/my_engine/users/auth'
require 'devise/models/id_card_authenticatable'
require 'devise/strategies/id_card_authenticatable'
routes = [nil, :new, :destroy]
config.add_module :id_card_authenticatable, strategy: true, route: { session: routes }
end

View file

@ -0,0 +1,76 @@
OpenIDConnect.logger = Rails.logger
OpenIDConnect.debug!
OmniAuth.config.on_failure = Proc.new { |env|
OmniAuth::FailureEndpoint.new(env).redirect_to_failure
}
OmniAuth.config.logger = Rails.logger
# Block GET requests to avoid exposing self to CVE-2015-9284
OmniAuth.config.allowed_request_methods = [:post]
signing_keys = ENV['tara_keys']
issuer = ENV['tara_issuer']
host = ENV['tara_host']
identifier = ENV['tara_identifier']
secret = ENV['tara_secret']
redirect_uri = ENV['tara_redirect_uri']
registrant_identifier = ENV['tara_rant_identifier']
registrant_secret = ENV['tara_rant_secret']
registrant_redirect_uri = ENV['tara_rant_redirect_uri']
Rails.application.config.middleware.use OmniAuth::Builder do
provider "tara", {
callback_path: '/registrar/open_id/callback',
name: 'tara',
scope: ['openid'],
state: Proc.new{ SecureRandom.hex(10) },
client_signing_alg: :RS256,
client_jwk_signing_key: signing_keys,
send_scope_to_token_endpoint: false,
send_nonce: true,
issuer: issuer,
client_options: {
scheme: 'https',
host: host,
authorization_endpoint: '/oidc/authorize',
token_endpoint: '/oidc/token',
userinfo_endpoint: nil, # Not implemented
jwks_uri: '/oidc/jwks',
# Registry
identifier: identifier,
secret: secret,
redirect_uri: redirect_uri,
},
}
provider "tara", {
callback_path: '/registrant/open_id/callback',
name: 'rant_tara',
scope: ['openid'],
client_signing_alg: :RS256,
client_jwk_signing_key: signing_keys,
send_scope_to_token_endpoint: false,
send_nonce: true,
issuer: issuer,
client_options: {
scheme: 'https',
host: host,
authorization_endpoint: '/oidc/authorize',
token_endpoint: '/oidc/token',
userinfo_endpoint: nil, # Not implemented
jwks_uri: '/oidc/jwks',
# Registry
identifier: registrant_identifier,
secret: registrant_secret,
redirect_uri: registrant_redirect_uri,
},
}
end

View file

@ -28,7 +28,10 @@ Truemail.configure do |config|
# Optional parameter. You can predefine default validation type for
# Truemail.validate('email@email.com') call without with-parameter
# Available validation types: :regex, :mx, :smtp
if Rails.env.production?
if ENV['default_email_validation_type'].present? &&
%w[regex mx smtp].include?(ENV['default_email_validation_type'])
config.default_validation_type = ENV['default_email_validation_type'].to_sym
elsif Rails.env.production?
config.default_validation_type = :mx
else
config.default_validation_type = :regex

View file

@ -2,4 +2,4 @@ en:
activerecord:
attributes:
account_activity:
created_at: Receipt date
created_at: Receipt date

View file

@ -295,6 +295,8 @@ en:
authentication_error: 'Authentication error'
sign_in_cancelled: "Sign in cancelled"
transfer_requested: 'Transfer requested.'
message_was_not_found: 'Message was not found'
only_one_parameter_allowed: 'Only one parameter allowed: %{param_1} or %{param_2}'
@ -658,3 +660,5 @@ en:
ipv6: IPv6
reference_no: Reference number
iban: IBAN
sign_in: "Sign in"
signed_in_successfully: "Signed in successfully"

View file

@ -2,11 +2,7 @@ en:
registrant:
sessions:
new:
header: Log in
header: Sign in with identity document
hint: >-
Access currently available only to Estonian citizens and e-residents with Estonian ID-card
or Mobile-ID.
login_mid:
header: Log in with mobile-id
submit_btn: Login
Sign in using Estonian (incl. e-residents) ID card, mobile ID,
Bank link or other EU citizen's electronic ID supported by EIDAS.

View file

@ -4,6 +4,14 @@ en:
new:
header_html: Eesti Interneti SA<br>Registrar Portal
submit_btn: Login
sign_in_with_identity_document: "Sign in with identity document"
identity_document_text: |
Sign in using Estonian (incl. e-residents) ID card, mobile ID,
Bank link or other EU citizen's electronic ID supported by EIDAS.
login_mid:
header: Log in with mobile-id
submit_btn: Login
tara:
callback:
header_html: "Eesti Interneti SA<br>Registrar Portal"
submit_btn: Login

View file

@ -0,0 +1,14 @@
en:
auth:
tara:
tampering: "Tampering detected. Sign in cancelled."
callback:
title: "Create a user"
errors: "prohibited this user from being saved"
form:
contact_data: "Contact Data"
data_from_identity_document: "Data from identity document"
new_password: "New password"
sign_up: "Sign up"

View file

@ -0,0 +1,14 @@
et:
auth:
tara:
tampering: "Avastatud urkimine. Sisselogimine tühistatud."
callback:
title: "Loo kasutaja"
errors: "seda kasutajat ei saa salvestada"
form:
contact_data: "Kontaktandmed"
data_from_identity_document: "Andmed elektroonselt isikutunnistuselt"
new_password: "Uus salasõna"
sign_up: "Registreeru"

View file

@ -61,10 +61,12 @@ Rails.application.routes.draw do
resource :registry_lock, only: %i[create destroy]
end
resources :contacts, only: %i[index show update], param: :uuid
resources :companies, only: %i[index]
end
resources :auctions, only: %i[index show update], param: :uuid
resources :bounces, only: %i[create]
end
match '*all', controller: 'cors', action: 'cors_preflight_check', via: [:options],
@ -77,17 +79,6 @@ Rails.application.routes.draw do
devise_for :users, path: '', class_name: 'ApiUser', skip: %i[sessions]
devise_scope :registrar_user do
get 'login/mid' => 'sessions#login_mid'
post 'login/mid' => 'sessions#mid'
post 'login/mid_status' => 'sessions#mid_status'
# /registrar/id path is hardcoded in Apache config for authentication with Estonian ID-card
post 'id' => 'sessions#id_card', as: :id_card_sign_in
post 'mid' => 'sessions#mid'
end
resources :invoices, except: %i[new create edit update destroy] do
resource :delivery, controller: 'invoices/delivery', only: %i[new create]
@ -164,6 +155,22 @@ Rails.application.routes.draw do
post 'sessions', to: 'registrar/sessions#create', as: :registrar_user_session
delete 'sign_out', to: 'registrar/sessions#destroy', as: :destroy_registrar_user_session
# TARA
match '/open_id/callback', via: %i[get post], to: 'sso/tara#registrar_callback'
match '/open_id/cancel', via: %i[get post delete], to: 'sso/tara#cancel'
end
end
scope :registrant do
devise_scope :registrant_user do
get 'sign_in', to: 'registrant/sessions#new', as: :new_registrant_user_session
post 'sessions', to: 'registrant/sessions#create', as: :registrant_user_session
delete 'sign_out', to: 'registrant/sessions#destroy', as: :destroy_registrant_user_session
# TARA
match '/open_id/callback', via: %i[get post], to: 'sso/tara#registrant_callback'
match '/open_id/cancel', via: %i[get post delete], to: 'sso/tara#cancel'
end
end
@ -172,19 +179,9 @@ Rails.application.routes.draw do
# POST /registrant/sign_in is not used
devise_for :users, path: '', class_name: 'RegistrantUser'
devise_scope :registrant_user do
get 'login/mid' => 'sessions#login_mid'
post 'login/mid' => 'sessions#mid'
post 'login/mid_status' => 'sessions#mid_status'
post 'mid' => 'sessions#mid'
# /registrant/id path is hardcoded in Apache config for authentication with Estonian ID-card
# Client certificate is asked only on login form submission, therefore the path must be different from the one in
# `new_registrant_user_session_path` route, in case some other auth type will be implemented
post 'id' => 'sessions#create', as: :id_card_sign_in
end
resources :registrars, only: :show
# resources :companies, only: :index
resources :domains, only: %i[index show] do
resources :contacts, only: %i[show edit update]
member do

View file

@ -1,236 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: controllers_diagram Pages: 1 -->
<svg width="1060pt" height="932pt"
viewBox="0.00 0.00 1060.24 932.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(436.494 484)">
<title>controllers_diagram</title>
<polygon fill="white" stroke="none" points="-436.494,448 -436.494,-484 623.742,-484 623.742,448 -436.494,448"/>
<!-- _diagram_info -->
<g id="node1" class="node"><title>_diagram_info</title>
<text text-anchor="start" x="224" y="-279.6" font-family="Times,serif" font-size="13.00">Controllers diagram</text>
<text text-anchor="start" x="224" y="-265.6" font-family="Times,serif" font-size="13.00">Date: Jul 08 2015 &#45; 13:40</text>
<text text-anchor="start" x="224" y="-251.6" font-family="Times,serif" font-size="13.00">Migration version: 20150707103801</text>
<text text-anchor="start" x="224" y="-237.6" font-family="Times,serif" font-size="13.00">Generated by RailRoady 1.3.0</text>
<text text-anchor="start" x="224" y="-223.6" font-family="Times,serif" font-size="13.00">http://railroady.prestonlee.com</text>
</g>
<!-- RegistrantController -->
<g id="node2" class="node"><title>RegistrantController</title>
<ellipse fill="none" stroke="black" cx="299" cy="426" rx="83.3857" ry="18"/>
<text text-anchor="middle" x="299" y="429.7" font-family="Times,serif" font-size="14.00">RegistrantController</text>
</g>
<!-- Epp::DomainsController -->
<g id="node3" class="node"><title>Epp::DomainsController</title>
<ellipse fill="none" stroke="black" cx="-322" cy="-150" rx="98.2828" ry="18"/>
<text text-anchor="middle" x="-322" y="-146.3" font-family="Times,serif" font-size="14.00">Epp::DomainsController</text>
</g>
<!-- Epp::SessionsController -->
<g id="node5" class="node"><title>Epp::SessionsController</title>
<ellipse fill="none" stroke="black" cx="24" cy="-450" rx="96.3833" ry="18"/>
<text text-anchor="middle" x="24" y="-446.3" font-family="Times,serif" font-size="14.00">Epp::SessionsController</text>
</g>
<!-- Epp::PollsController -->
<g id="node6" class="node"><title>Epp::PollsController</title>
<ellipse fill="none" stroke="black" cx="491" cy="426" rx="83.3857" ry="18"/>
<text text-anchor="middle" x="491" y="429.7" font-family="Times,serif" font-size="14.00">Epp::PollsController</text>
</g>
<!-- Epp::ContactsController -->
<g id="node7" class="node"><title>Epp::ContactsController</title>
<ellipse fill="none" stroke="black" cx="97" cy="426" rx="96.6831" ry="18"/>
<text text-anchor="middle" x="97" y="429.7" font-family="Times,serif" font-size="14.00">Epp::ContactsController</text>
</g>
<!-- Epp::ErrorsController -->
<g id="node8" class="node"><title>Epp::ErrorsController</title>
<ellipse fill="none" stroke="black" cx="532" cy="-462" rx="87.9851" ry="18"/>
<text text-anchor="middle" x="532" y="-458.3" font-family="Times,serif" font-size="14.00">Epp::ErrorsController</text>
</g>
<!-- RegistrarController -->
<g id="node10" class="node"><title>RegistrarController</title>
<ellipse fill="none" stroke="black" cx="-173" cy="-462" rx="79.0865" ry="18"/>
<text text-anchor="middle" x="-173" y="-458.3" font-family="Times,serif" font-size="14.00">RegistrarController</text>
</g>
<!-- Admin::DomainsController -->
<g id="node11" class="node"><title>Admin::DomainsController</title>
<ellipse fill="none" stroke="black" cx="-203" cy="-270" rx="108.581" ry="18"/>
<text text-anchor="middle" x="-203" y="-266.3" font-family="Times,serif" font-size="14.00">Admin::DomainsController</text>
</g>
<!-- Admin::DelayedJobsController -->
<g id="node12" class="node"><title>Admin::DelayedJobsController</title>
<ellipse fill="none" stroke="black" cx="-106" cy="-54" rx="121.578" ry="18"/>
<text text-anchor="middle" x="-106" y="-50.3" font-family="Times,serif" font-size="14.00">Admin::DelayedJobsController</text>
</g>
<!-- Admin::WhiteIpsController -->
<g id="node13" class="node"><title>Admin::WhiteIpsController</title>
<ellipse fill="none" stroke="black" cx="-215" cy="306" rx="109.381" ry="18"/>
<text text-anchor="middle" x="-215" y="309.7" font-family="Times,serif" font-size="14.00">Admin::WhiteIpsController</text>
</g>
<!-- Admin::ZonefilesController -->
<g id="node15" class="node"><title>Admin::ZonefilesController</title>
<ellipse fill="none" stroke="black" cx="-46" cy="-390" rx="109.681" ry="18"/>
<text text-anchor="middle" x="-46" y="-386.3" font-family="Times,serif" font-size="14.00">Admin::ZonefilesController</text>
</g>
<!-- Admin::SettingsController -->
<g id="node16" class="node"><title>Admin::SettingsController</title>
<ellipse fill="none" stroke="black" cx="249" cy="-414" rx="104.782" ry="18"/>
<text text-anchor="middle" x="249" y="-410.3" font-family="Times,serif" font-size="14.00">Admin::SettingsController</text>
</g>
<!-- Admin::ApiUsersController -->
<g id="node17" class="node"><title>Admin::ApiUsersController</title>
<ellipse fill="none" stroke="black" cx="110" cy="366" rx="109.681" ry="18"/>
<text text-anchor="middle" x="110" y="369.7" font-family="Times,serif" font-size="14.00">Admin::ApiUsersController</text>
</g>
<!-- Admin::SessionsController -->
<g id="node19" class="node"><title>Admin::SessionsController</title>
<ellipse fill="none" stroke="black" cx="347" cy="366" rx="106.681" ry="18"/>
<text text-anchor="middle" x="347" y="369.7" font-family="Times,serif" font-size="14.00">Admin::SessionsController</text>
</g>
<!-- Admin::DomainVersionsController -->
<g id="node20" class="node"><title>Admin::DomainVersionsController</title>
<ellipse fill="none" stroke="black" cx="232" cy="-114" rx="136.476" ry="18"/>
<text text-anchor="middle" x="232" y="-110.3" font-family="Times,serif" font-size="14.00">Admin::DomainVersionsController</text>
</g>
<!-- Admin::ContactsController -->
<g id="node21" class="node"><title>Admin::ContactsController</title>
<ellipse fill="none" stroke="black" cx="491" cy="-402" rx="107.482" ry="18"/>
<text text-anchor="middle" x="491" y="-398.3" font-family="Times,serif" font-size="14.00">Admin::ContactsController</text>
</g>
<!-- Admin::CertificatesController -->
<g id="node22" class="node"><title>Admin::CertificatesController</title>
<ellipse fill="none" stroke="black" cx="69" cy="-294" rx="116.979" ry="18"/>
<text text-anchor="middle" x="69" y="-290.3" font-family="Times,serif" font-size="14.00">Admin::CertificatesController</text>
</g>
<!-- Admin::BankStatementsController -->
<g id="node23" class="node"><title>Admin::BankStatementsController</title>
<ellipse fill="none" stroke="black" cx="326" cy="6" rx="133.776" ry="18"/>
<text text-anchor="middle" x="326" y="9.7" font-family="Times,serif" font-size="14.00">Admin::BankStatementsController</text>
</g>
<!-- Admin::BankTransactionsController -->
<g id="node24" class="node"><title>Admin::BankTransactionsController</title>
<ellipse fill="none" stroke="black" cx="140" cy="126" rx="139.976" ry="18"/>
<text text-anchor="middle" x="140" y="129.7" font-family="Times,serif" font-size="14.00">Admin::BankTransactionsController</text>
</g>
<!-- Admin::BlockedDomainsController -->
<g id="node25" class="node"><title>Admin::BlockedDomainsController</title>
<ellipse fill="none" stroke="black" cx="294" cy="-174" rx="137.576" ry="18"/>
<text text-anchor="middle" x="294" y="-170.3" font-family="Times,serif" font-size="14.00">Admin::BlockedDomainsController</text>
</g>
<!-- Admin::DashboardsController -->
<g id="node26" class="node"><title>Admin::DashboardsController</title>
<ellipse fill="none" stroke="black" cx="118" cy="246" rx="118.079" ry="18"/>
<text text-anchor="middle" x="118" y="249.7" font-family="Times,serif" font-size="14.00">Admin::DashboardsController</text>
</g>
<!-- Admin::RegistrarsController -->
<g id="node28" class="node"><title>Admin::RegistrarsController</title>
<ellipse fill="none" stroke="black" cx="412" cy="186" rx="112.38" ry="18"/>
<text text-anchor="middle" x="412" y="189.7" font-family="Times,serif" font-size="14.00">Admin::RegistrarsController</text>
</g>
<!-- Admin::ReppLogsController -->
<g id="node29" class="node"><title>Admin::ReppLogsController</title>
<ellipse fill="none" stroke="black" cx="412" cy="126" rx="112.38" ry="18"/>
<text text-anchor="middle" x="412" y="129.7" font-family="Times,serif" font-size="14.00">Admin::ReppLogsController</text>
</g>
<!-- Admin::InvoicesController -->
<g id="node30" class="node"><title>Admin::InvoicesController</title>
<ellipse fill="none" stroke="black" cx="-277" cy="-210" rx="106.681" ry="18"/>
<text text-anchor="middle" x="-277" y="-206.3" font-family="Times,serif" font-size="14.00">Admin::InvoicesController</text>
</g>
<!-- Admin::AdminUsersController -->
<g id="node31" class="node"><title>Admin::AdminUsersController</title>
<ellipse fill="none" stroke="black" cx="386" cy="246" rx="121.578" ry="18"/>
<text text-anchor="middle" x="386" y="249.7" font-family="Times,serif" font-size="14.00">Admin::AdminUsersController</text>
</g>
<!-- Admin::EppLogsController -->
<g id="node32" class="node"><title>Admin::EppLogsController</title>
<ellipse fill="none" stroke="black" cx="-275" cy="366" rx="108.581" ry="18"/>
<text text-anchor="middle" x="-275" y="369.7" font-family="Times,serif" font-size="14.00">Admin::EppLogsController</text>
</g>
<!-- Admin::LegalDocumentsController -->
<g id="node33" class="node"><title>Admin::LegalDocumentsController</title>
<ellipse fill="none" stroke="black" cx="-7" cy="-174" rx="137.276" ry="18"/>
<text text-anchor="middle" x="-7" y="-170.3" font-family="Times,serif" font-size="14.00">Admin::LegalDocumentsController</text>
</g>
<!-- ApplicationController -->
<g id="node34" class="node"><title>ApplicationController</title>
<ellipse fill="none" stroke="black" cx="-344" cy="-90" rx="88.2844" ry="18"/>
<text text-anchor="middle" x="-344" y="-86.3" font-family="Times,serif" font-size="14.00">ApplicationController</text>
</g>
<!-- Registrar::DomainsController -->
<g id="node35" class="node"><title>Registrar::DomainsController</title>
<ellipse fill="none" stroke="black" cx="-196" cy="-330" rx="116.18" ry="18"/>
<text text-anchor="middle" x="-196" y="-326.3" font-family="Times,serif" font-size="14.00">Registrar::DomainsController</text>
</g>
<!-- Registrar::SessionsController -->
<g id="node37" class="node"><title>Registrar::SessionsController</title>
<ellipse fill="none" stroke="black" cx="114" cy="306" rx="114.28" ry="18"/>
<text text-anchor="middle" x="114" y="309.7" font-family="Times,serif" font-size="14.00">Registrar::SessionsController</text>
</g>
<!-- Registrar::PollsController -->
<g id="node38" class="node"><title>Registrar::PollsController</title>
<ellipse fill="none" stroke="black" cx="509" cy="-54" rx="101.282" ry="18"/>
<text text-anchor="middle" x="509" y="-50.3" font-family="Times,serif" font-size="14.00">Registrar::PollsController</text>
</g>
<!-- Registrar::DepositsController -->
<g id="node39" class="node"><title>Registrar::DepositsController</title>
<ellipse fill="none" stroke="black" cx="366" cy="306" rx="114.28" ry="18"/>
<text text-anchor="middle" x="366" y="309.7" font-family="Times,serif" font-size="14.00">Registrar::DepositsController</text>
</g>
<!-- Registrar::ContactsController -->
<g id="node40" class="node"><title>Registrar::ContactsController</title>
<ellipse fill="none" stroke="black" cx="438" cy="66" rx="114.28" ry="18"/>
<text text-anchor="middle" x="438" y="69.7" font-family="Times,serif" font-size="14.00">Registrar::ContactsController</text>
</g>
<!-- Registrar::DeppController -->
<g id="node41" class="node"><title>Registrar::DeppController</title>
<ellipse fill="none" stroke="black" cx="-305" cy="6" rx="102.882" ry="18"/>
<text text-anchor="middle" x="-305" y="9.7" font-family="Times,serif" font-size="14.00">Registrar::DeppController</text>
</g>
<!-- Registrar::NameserversController -->
<g id="node42" class="node"><title>Registrar::NameserversController</title>
<ellipse fill="none" stroke="black" cx="58" cy="-234" rx="129.977" ry="18"/>
<text text-anchor="middle" x="58" y="-230.3" font-family="Times,serif" font-size="14.00">Registrar::NameserversController</text>
</g>
<!-- Registrar::XmlConsolesController -->
<g id="node43" class="node"><title>Registrar::XmlConsolesController</title>
<ellipse fill="none" stroke="black" cx="-60" cy="-114" rx="131.877" ry="18"/>
<text text-anchor="middle" x="-60" y="-110.3" font-family="Times,serif" font-size="14.00">Registrar::XmlConsolesController</text>
</g>
<!-- Registrar::InvoicesController -->
<g id="node44" class="node"><title>Registrar::InvoicesController</title>
<ellipse fill="none" stroke="black" cx="438" cy="-342" rx="113.98" ry="18"/>
<text text-anchor="middle" x="438" y="-338.3" font-family="Times,serif" font-size="14.00">Registrar::InvoicesController</text>
</g>
<!-- Registrar::AccountActivitiesController -->
<g id="node45" class="node"><title>Registrar::AccountActivitiesController</title>
<ellipse fill="none" stroke="black" cx="148" cy="66" rx="147.574" ry="18"/>
<text text-anchor="middle" x="148" y="69.7" font-family="Times,serif" font-size="14.00">Registrar::AccountActivitiesController</text>
</g>
<!-- Registrant::DomainsController -->
<g id="node46" class="node"><title>Registrant::DomainsController</title>
<ellipse fill="none" stroke="black" cx="-144" cy="126" rx="120.479" ry="18"/>
<text text-anchor="middle" x="-144" y="129.7" font-family="Times,serif" font-size="14.00">Registrant::DomainsController</text>
</g>
<!-- Registrant::SessionsController -->
<g id="node47" class="node"><title>Registrant::SessionsController</title>
<ellipse fill="none" stroke="black" cx="-146" cy="186" rx="118.079" ry="18"/>
<text text-anchor="middle" x="-146" y="189.7" font-family="Times,serif" font-size="14.00">Registrant::SessionsController</text>
</g>
<!-- Registrant::DomainUpdateConfirmsController -->
<g id="node48" class="node"><title>Registrant::DomainUpdateConfirmsController</title>
<ellipse fill="none" stroke="black" cx="-5" cy="6" rx="175.469" ry="18"/>
<text text-anchor="middle" x="-5" y="9.7" font-family="Times,serif" font-size="14.00">Registrant::DomainUpdateConfirmsController</text>
</g>
<!-- Registrant::WhoisController -->
<g id="node49" class="node"><title>Registrant::WhoisController</title>
<ellipse fill="none" stroke="black" cx="507" cy="-114" rx="111.28" ry="18"/>
<text text-anchor="middle" x="507" y="-110.3" font-family="Times,serif" font-size="14.00">Registrant::WhoisController</text>
</g>
<!-- Registrant::DomainDeleteConfirmsController -->
<g id="node50" class="node"><title>Registrant::DomainDeleteConfirmsController</title>
<ellipse fill="none" stroke="black" cx="209" cy="-54" rx="172.769" ry="18"/>
<text text-anchor="middle" x="209" y="-50.3" font-family="Times,serif" font-size="14.00">Registrant::DomainDeleteConfirmsController</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 15 KiB

View file

@ -1,614 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: controllers_diagram Pages: 1 -->
<svg width="1612pt" height="1548pt"
viewBox="0.00 0.00 1612.00 1547.50" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(724 843.5)">
<title>controllers_diagram</title>
<polygon fill="white" stroke="none" points="-724,704 -724,-843.5 888,-843.5 888,704 -724,704"/>
<!-- _diagram_info -->
<g id="node1" class="node"><title>_diagram_info</title>
<text text-anchor="start" x="628" y="556.4" font-family="Times,serif" font-size="13.00">Controllers diagram</text>
<text text-anchor="start" x="628" y="570.4" font-family="Times,serif" font-size="13.00">Date: Jul 08 2015 &#45; 13:40</text>
<text text-anchor="start" x="628" y="584.4" font-family="Times,serif" font-size="13.00">Migration version: 20150707103801</text>
<text text-anchor="start" x="628" y="598.4" font-family="Times,serif" font-size="13.00">Generated by RailRoady 1.3.0</text>
<text text-anchor="start" x="628" y="612.4" font-family="Times,serif" font-size="13.00">http://railroady.prestonlee.com</text>
</g>
<!-- RegistrantController -->
<g id="node2" class="node"><title>RegistrantController</title>
<path fill="none" stroke="black" d="M-448,699.5C-448,699.5 -344,699.5 -344,699.5 -338,699.5 -332,693.5 -332,687.5 -332,687.5 -332,618.5 -332,618.5 -332,612.5 -338,606.5 -344,606.5 -344,606.5 -448,606.5 -448,606.5 -454,606.5 -460,612.5 -460,618.5 -460,618.5 -460,687.5 -460,687.5 -460,693.5 -454,699.5 -448,699.5"/>
<text text-anchor="middle" x="-396" y="621.7" font-family="Times,serif" font-size="14.00">RegistrantController</text>
<polyline fill="none" stroke="black" points="-460,629.5 -332,629.5 "/>
<text text-anchor="start" x="-452" y="644.7" font-family="Times,serif" font-size="14.00">head_title_sufix</text>
<polyline fill="none" stroke="black" points="-460,652.5 -332,652.5 "/>
<polyline fill="none" stroke="black" points="-460,676.5 -332,676.5 "/>
<text text-anchor="start" x="-452" y="691.7" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Epp::DomainsController -->
<g id="node3" class="node"><title>Epp::DomainsController</title>
<path fill="none" stroke="black" d="M112.5,99C112.5,99 239.5,99 239.5,99 245.5,99 251.5,93 251.5,87 251.5,87 251.5,-237 251.5,-237 251.5,-243 245.5,-249 239.5,-249 239.5,-249 112.5,-249 112.5,-249 106.5,-249 100.5,-243 100.5,-237 100.5,-237 100.5,87 100.5,87 100.5,93 106.5,99 112.5,99"/>
<text text-anchor="middle" x="176" y="-233.8" font-family="Times,serif" font-size="14.00">Epp::DomainsController</text>
<polyline fill="none" stroke="black" points="100.5,-226 251.5,-226 "/>
<text text-anchor="start" x="108.5" y="-210.8" font-family="Times,serif" font-size="14.00">check</text>
<text text-anchor="start" x="108.5" y="-195.8" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="108.5" y="-180.8" font-family="Times,serif" font-size="14.00">delete</text>
<text text-anchor="start" x="108.5" y="-165.8" font-family="Times,serif" font-size="14.00">info</text>
<text text-anchor="start" x="108.5" y="-150.8" font-family="Times,serif" font-size="14.00">renew</text>
<text text-anchor="start" x="108.5" y="-135.8" font-family="Times,serif" font-size="14.00">transfer</text>
<text text-anchor="start" x="108.5" y="-120.8" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="100.5,-113 251.5,-113 "/>
<polyline fill="none" stroke="black" points="100.5,-89 251.5,-89 "/>
<text text-anchor="start" x="108.5" y="-73.8" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="108.5" y="-58.8" font-family="Times,serif" font-size="14.00">balance_ok?</text>
<text text-anchor="start" x="108.5" y="-43.8" font-family="Times,serif" font-size="14.00">find_domain</text>
<text text-anchor="start" x="108.5" y="-28.8" font-family="Times,serif" font-size="14.00">find_password</text>
<text text-anchor="start" x="108.5" y="-13.8" font-family="Times,serif" font-size="14.00">status_editing_disabled</text>
<text text-anchor="start" x="108.5" y="1.2" font-family="Times,serif" font-size="14.00">validate_check</text>
<text text-anchor="start" x="108.5" y="16.2" font-family="Times,serif" font-size="14.00">validate_create</text>
<text text-anchor="start" x="108.5" y="31.2" font-family="Times,serif" font-size="14.00">validate_delete</text>
<text text-anchor="start" x="108.5" y="46.2" font-family="Times,serif" font-size="14.00">validate_info</text>
<text text-anchor="start" x="108.5" y="61.2" font-family="Times,serif" font-size="14.00">validate_renew</text>
<text text-anchor="start" x="108.5" y="76.2" font-family="Times,serif" font-size="14.00">validate_transfer</text>
<text text-anchor="start" x="108.5" y="91.2" font-family="Times,serif" font-size="14.00">validate_update</text>
</g>
<!-- Epp::SessionsController -->
<g id="node5" class="node"><title>Epp::SessionsController</title>
<path fill="none" stroke="black" d="M532,-320.5C532,-320.5 656,-320.5 656,-320.5 662,-320.5 668,-326.5 668,-332.5 668,-332.5 668,-491.5 668,-491.5 668,-497.5 662,-503.5 656,-503.5 656,-503.5 532,-503.5 532,-503.5 526,-503.5 520,-497.5 520,-491.5 520,-491.5 520,-332.5 520,-332.5 520,-326.5 526,-320.5 532,-320.5"/>
<text text-anchor="middle" x="594" y="-488.3" font-family="Times,serif" font-size="14.00">Epp::SessionsController</text>
<polyline fill="none" stroke="black" points="520,-480.5 668,-480.5 "/>
<text text-anchor="start" x="528" y="-450.3" font-family="Times,serif" font-size="14.00">hello</text>
<text text-anchor="start" x="528" y="-435.3" font-family="Times,serif" font-size="14.00">ip_white?</text>
<text text-anchor="start" x="528" y="-420.3" font-family="Times,serif" font-size="14.00">login</text>
<text text-anchor="start" x="528" y="-405.3" font-family="Times,serif" font-size="14.00">login_params</text>
<text text-anchor="start" x="528" y="-390.3" font-family="Times,serif" font-size="14.00">logout</text>
<text text-anchor="start" x="528" y="-375.3" font-family="Times,serif" font-size="14.00">parsed_frame</text>
<polyline fill="none" stroke="black" points="520,-367.5 668,-367.5 "/>
<polyline fill="none" stroke="black" points="520,-343.5 668,-343.5 "/>
<text text-anchor="start" x="528" y="-328.3" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Epp::PollsController -->
<g id="node6" class="node"><title>Epp::PollsController</title>
<path fill="none" stroke="black" d="M-288,-561C-288,-561 -184,-561 -184,-561 -178,-561 -172,-567 -172,-573 -172,-573 -172,-687 -172,-687 -172,-693 -178,-699 -184,-699 -184,-699 -288,-699 -288,-699 -294,-699 -300,-693 -300,-687 -300,-687 -300,-573 -300,-573 -300,-567 -294,-561 -288,-561"/>
<text text-anchor="middle" x="-236" y="-683.8" font-family="Times,serif" font-size="14.00">Epp::PollsController</text>
<polyline fill="none" stroke="black" points="-300,-676 -172,-676 "/>
<text text-anchor="start" x="-292" y="-645.8" font-family="Times,serif" font-size="14.00">poll</text>
<polyline fill="none" stroke="black" points="-300,-623 -172,-623 "/>
<polyline fill="none" stroke="black" points="-300,-599 -172,-599 "/>
<text text-anchor="start" x="-292" y="-583.8" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="-292" y="-568.8" font-family="Times,serif" font-size="14.00">validate_poll</text>
</g>
<!-- Epp::ContactsController -->
<g id="node7" class="node"><title>Epp::ContactsController</title>
<path fill="none" stroke="black" d="M-68.5,-221C-68.5,-221 56.5,-221 56.5,-221 62.5,-221 68.5,-227 68.5,-233 68.5,-233 68.5,-527 68.5,-527 68.5,-533 62.5,-539 56.5,-539 56.5,-539 -68.5,-539 -68.5,-539 -74.5,-539 -80.5,-533 -80.5,-527 -80.5,-527 -80.5,-233 -80.5,-233 -80.5,-227 -74.5,-221 -68.5,-221"/>
<text text-anchor="middle" x="-6" y="-523.8" font-family="Times,serif" font-size="14.00">Epp::ContactsController</text>
<polyline fill="none" stroke="black" points="-80.5,-516 68.5,-516 "/>
<text text-anchor="start" x="-72.5" y="-500.8" font-family="Times,serif" font-size="14.00">check</text>
<text text-anchor="start" x="-72.5" y="-485.8" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="-72.5" y="-470.8" font-family="Times,serif" font-size="14.00">delete</text>
<text text-anchor="start" x="-72.5" y="-455.8" font-family="Times,serif" font-size="14.00">info</text>
<text text-anchor="start" x="-72.5" y="-440.8" font-family="Times,serif" font-size="14.00">renew</text>
<text text-anchor="start" x="-72.5" y="-425.8" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="-80.5,-418 68.5,-418 "/>
<polyline fill="none" stroke="black" points="-80.5,-394 68.5,-394 "/>
<text text-anchor="start" x="-72.5" y="-378.8" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="-72.5" y="-363.8" font-family="Times,serif" font-size="14.00">contact_org_disabled</text>
<text text-anchor="start" x="-72.5" y="-348.8" font-family="Times,serif" font-size="14.00">fax_disabled</text>
<text text-anchor="start" x="-72.5" y="-333.8" font-family="Times,serif" font-size="14.00">find_contact</text>
<text text-anchor="start" x="-72.5" y="-318.8" font-family="Times,serif" font-size="14.00">find_password</text>
<text text-anchor="start" x="-72.5" y="-303.8" font-family="Times,serif" font-size="14.00">status_editing_disabled</text>
<text text-anchor="start" x="-72.5" y="-288.8" font-family="Times,serif" font-size="14.00">validate_check</text>
<text text-anchor="start" x="-72.5" y="-273.8" font-family="Times,serif" font-size="14.00">validate_create</text>
<text text-anchor="start" x="-72.5" y="-258.8" font-family="Times,serif" font-size="14.00">validate_delete</text>
<text text-anchor="start" x="-72.5" y="-243.8" font-family="Times,serif" font-size="14.00">validate_info</text>
<text text-anchor="start" x="-72.5" y="-228.8" font-family="Times,serif" font-size="14.00">validate_update</text>
</g>
<!-- Epp::ErrorsController -->
<g id="node8" class="node"><title>Epp::ErrorsController</title>
<path fill="none" stroke="black" d="M752.5,79C752.5,79 863.5,79 863.5,79 869.5,79 875.5,73 875.5,67 875.5,67 875.5,-17 875.5,-17 875.5,-23 869.5,-29 863.5,-29 863.5,-29 752.5,-29 752.5,-29 746.5,-29 740.5,-23 740.5,-17 740.5,-17 740.5,67 740.5,67 740.5,73 746.5,79 752.5,79"/>
<text text-anchor="middle" x="808" y="-13.8" font-family="Times,serif" font-size="14.00">Epp::ErrorsController</text>
<polyline fill="none" stroke="black" points="740.5,-6 875.5,-6 "/>
<text text-anchor="start" x="748.5" y="9.2" font-family="Times,serif" font-size="14.00">error</text>
<polyline fill="none" stroke="black" points="740.5,32 875.5,32 "/>
<polyline fill="none" stroke="black" points="740.5,56 875.5,56 "/>
<text text-anchor="start" x="748.5" y="71.2" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- RegistrarController -->
<g id="node10" class="node"><title>RegistrarController</title>
<path fill="none" stroke="black" d="M-708,539.5C-708,539.5 -610,539.5 -610,539.5 -604,539.5 -598,533.5 -598,527.5 -598,527.5 -598,428.5 -598,428.5 -598,422.5 -604,416.5 -610,416.5 -610,416.5 -708,416.5 -708,416.5 -714,416.5 -720,422.5 -720,428.5 -720,428.5 -720,527.5 -720,527.5 -720,533.5 -714,539.5 -708,539.5"/>
<text text-anchor="middle" x="-659" y="431.7" font-family="Times,serif" font-size="14.00">RegistrarController</text>
<polyline fill="none" stroke="black" points="-720,439.5 -598,439.5 "/>
<polyline fill="none" stroke="black" points="-720,492.5 -598,492.5 "/>
<polyline fill="none" stroke="black" points="-720,516.5 -598,516.5 "/>
<text text-anchor="start" x="-712" y="531.7" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Admin::DomainsController -->
<g id="node11" class="node"><title>Admin::DomainsController</title>
<path fill="none" stroke="black" d="M-268.5,-1C-268.5,-1 -125.5,-1 -125.5,-1 -119.5,-1 -113.5,-7 -113.5,-13 -113.5,-13 -113.5,-217 -113.5,-217 -113.5,-223 -119.5,-229 -125.5,-229 -125.5,-229 -268.5,-229 -268.5,-229 -274.5,-229 -280.5,-223 -280.5,-217 -280.5,-217 -280.5,-13 -280.5,-13 -280.5,-7 -274.5,-1 -268.5,-1"/>
<text text-anchor="middle" x="-197" y="-213.8" font-family="Times,serif" font-size="14.00">Admin::DomainsController</text>
<polyline fill="none" stroke="black" points="-280.5,-206 -113.5,-206 "/>
<text text-anchor="start" x="-272.5" y="-190.8" font-family="Times,serif" font-size="14.00">edit</text>
<text text-anchor="start" x="-272.5" y="-175.8" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="-272.5" y="-160.8" font-family="Times,serif" font-size="14.00">set_force_delete</text>
<text text-anchor="start" x="-272.5" y="-145.8" font-family="Times,serif" font-size="14.00">show</text>
<text text-anchor="start" x="-272.5" y="-130.8" font-family="Times,serif" font-size="14.00">unset_force_delete</text>
<text text-anchor="start" x="-272.5" y="-115.8" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="-280.5,-108 -113.5,-108 "/>
<polyline fill="none" stroke="black" points="-280.5,-84 -113.5,-84 "/>
<text text-anchor="start" x="-272.5" y="-68.8" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="-272.5" y="-53.8" font-family="Times,serif" font-size="14.00">build_associations</text>
<text text-anchor="start" x="-272.5" y="-38.8" font-family="Times,serif" font-size="14.00">domain_params</text>
<text text-anchor="start" x="-272.5" y="-23.8" font-family="Times,serif" font-size="14.00">ignore_empty_statuses</text>
<text text-anchor="start" x="-272.5" y="-8.8" font-family="Times,serif" font-size="14.00">set_domain</text>
</g>
<!-- Admin::DelayedJobsController -->
<g id="node12" class="node"><title>Admin::DelayedJobsController</title>
<path fill="none" stroke="black" d="M-88.5,619.5C-88.5,619.5 74.5,619.5 74.5,619.5 80.5,619.5 86.5,613.5 86.5,607.5 86.5,607.5 86.5,538.5 86.5,538.5 86.5,532.5 80.5,526.5 74.5,526.5 74.5,526.5 -88.5,526.5 -88.5,526.5 -94.5,526.5 -100.5,532.5 -100.5,538.5 -100.5,538.5 -100.5,607.5 -100.5,607.5 -100.5,613.5 -94.5,619.5 -88.5,619.5"/>
<text text-anchor="middle" x="-7" y="541.7" font-family="Times,serif" font-size="14.00">Admin::DelayedJobsController</text>
<polyline fill="none" stroke="black" points="-100.5,549.5 86.5,549.5 "/>
<text text-anchor="start" x="-92.5" y="564.7" font-family="Times,serif" font-size="14.00">index</text>
<polyline fill="none" stroke="black" points="-100.5,572.5 86.5,572.5 "/>
<polyline fill="none" stroke="black" points="-100.5,596.5 86.5,596.5 "/>
<text text-anchor="start" x="-92.5" y="611.7" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Admin::WhiteIpsController -->
<g id="node13" class="node"><title>Admin::WhiteIpsController</title>
<path fill="none" stroke="black" d="M-488,239C-488,239 -344,239 -344,239 -338,239 -332,233 -332,227 -332,227 -332,53 -332,53 -332,47 -338,41 -344,41 -344,41 -488,41 -488,41 -494,41 -500,47 -500,53 -500,53 -500,227 -500,227 -500,233 -494,239 -488,239"/>
<text text-anchor="middle" x="-416" y="56.2" font-family="Times,serif" font-size="14.00">Admin::WhiteIpsController</text>
<polyline fill="none" stroke="black" points="-500,64 -332,64 "/>
<text text-anchor="start" x="-492" y="79.2" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="-492" y="94.2" font-family="Times,serif" font-size="14.00">destroy</text>
<text text-anchor="start" x="-492" y="109.2" font-family="Times,serif" font-size="14.00">edit</text>
<text text-anchor="start" x="-492" y="124.2" font-family="Times,serif" font-size="14.00">new</text>
<text text-anchor="start" x="-492" y="139.2" font-family="Times,serif" font-size="14.00">show</text>
<text text-anchor="start" x="-492" y="154.2" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="-500,162 -332,162 "/>
<polyline fill="none" stroke="black" points="-500,186 -332,186 "/>
<text text-anchor="start" x="-492" y="201.2" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="-492" y="216.2" font-family="Times,serif" font-size="14.00">set_registrar</text>
<text text-anchor="start" x="-492" y="231.2" font-family="Times,serif" font-size="14.00">white_ip_params</text>
</g>
<!-- Admin::ZonefilesController -->
<g id="node15" class="node"><title>Admin::ZonefilesController</title>
<path fill="none" stroke="black" d="M-688.5,-240.5C-688.5,-240.5 -543.5,-240.5 -543.5,-240.5 -537.5,-240.5 -531.5,-246.5 -531.5,-252.5 -531.5,-252.5 -531.5,-321.5 -531.5,-321.5 -531.5,-327.5 -537.5,-333.5 -543.5,-333.5 -543.5,-333.5 -688.5,-333.5 -688.5,-333.5 -694.5,-333.5 -700.5,-327.5 -700.5,-321.5 -700.5,-321.5 -700.5,-252.5 -700.5,-252.5 -700.5,-246.5 -694.5,-240.5 -688.5,-240.5"/>
<text text-anchor="middle" x="-616" y="-318.3" font-family="Times,serif" font-size="14.00">Admin::ZonefilesController</text>
<polyline fill="none" stroke="black" points="-700.5,-310.5 -531.5,-310.5 "/>
<text text-anchor="start" x="-692.5" y="-295.3" font-family="Times,serif" font-size="14.00">create</text>
<polyline fill="none" stroke="black" points="-700.5,-287.5 -531.5,-287.5 "/>
<polyline fill="none" stroke="black" points="-700.5,-263.5 -531.5,-263.5 "/>
<text text-anchor="start" x="-692.5" y="-248.3" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Admin::SettingsController -->
<g id="node16" class="node"><title>Admin::SettingsController</title>
<path fill="none" stroke="black" d="M552.5,-540.5C552.5,-540.5 689.5,-540.5 689.5,-540.5 695.5,-540.5 701.5,-546.5 701.5,-552.5 701.5,-552.5 701.5,-711.5 701.5,-711.5 701.5,-717.5 695.5,-723.5 689.5,-723.5 689.5,-723.5 552.5,-723.5 552.5,-723.5 546.5,-723.5 540.5,-717.5 540.5,-711.5 540.5,-711.5 540.5,-552.5 540.5,-552.5 540.5,-546.5 546.5,-540.5 552.5,-540.5"/>
<text text-anchor="middle" x="621" y="-708.3" font-family="Times,serif" font-size="14.00">Admin::SettingsController</text>
<polyline fill="none" stroke="black" points="540.5,-700.5 701.5,-700.5 "/>
<text text-anchor="start" x="548.5" y="-685.3" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="548.5" y="-670.3" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="548.5" y="-655.3" font-family="Times,serif" font-size="14.00">show</text>
<text text-anchor="start" x="548.5" y="-640.3" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="540.5,-632.5 701.5,-632.5 "/>
<polyline fill="none" stroke="black" points="540.5,-608.5 701.5,-608.5 "/>
<text text-anchor="start" x="548.5" y="-593.3" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="548.5" y="-578.3" font-family="Times,serif" font-size="14.00">casted_settings</text>
<text text-anchor="start" x="548.5" y="-563.3" font-family="Times,serif" font-size="14.00">set_setting_group</text>
<text text-anchor="start" x="548.5" y="-548.3" font-family="Times,serif" font-size="14.00">setting_group_params</text>
</g>
<!-- Admin::ApiUsersController -->
<g id="node17" class="node"><title>Admin::ApiUsersController</title>
<path fill="none" stroke="black" d="M111.5,-300.5C111.5,-300.5 256.5,-300.5 256.5,-300.5 262.5,-300.5 268.5,-306.5 268.5,-312.5 268.5,-312.5 268.5,-501.5 268.5,-501.5 268.5,-507.5 262.5,-513.5 256.5,-513.5 256.5,-513.5 111.5,-513.5 111.5,-513.5 105.5,-513.5 99.5,-507.5 99.5,-501.5 99.5,-501.5 99.5,-312.5 99.5,-312.5 99.5,-306.5 105.5,-300.5 111.5,-300.5"/>
<text text-anchor="middle" x="184" y="-498.3" font-family="Times,serif" font-size="14.00">Admin::ApiUsersController</text>
<polyline fill="none" stroke="black" points="99.5,-490.5 268.5,-490.5 "/>
<text text-anchor="start" x="107.5" y="-475.3" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="107.5" y="-460.3" font-family="Times,serif" font-size="14.00">destroy</text>
<text text-anchor="start" x="107.5" y="-445.3" font-family="Times,serif" font-size="14.00">edit</text>
<text text-anchor="start" x="107.5" y="-430.3" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="107.5" y="-415.3" font-family="Times,serif" font-size="14.00">new</text>
<text text-anchor="start" x="107.5" y="-400.3" font-family="Times,serif" font-size="14.00">show</text>
<text text-anchor="start" x="107.5" y="-385.3" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="99.5,-377.5 268.5,-377.5 "/>
<polyline fill="none" stroke="black" points="99.5,-353.5 268.5,-353.5 "/>
<text text-anchor="start" x="107.5" y="-338.3" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="107.5" y="-323.3" font-family="Times,serif" font-size="14.00">api_user_params</text>
<text text-anchor="start" x="107.5" y="-308.3" font-family="Times,serif" font-size="14.00">set_api_user</text>
</g>
<!-- Admin::SessionsController -->
<g id="node19" class="node"><title>Admin::SessionsController</title>
<path fill="none" stroke="black" d="M-688,-101C-688,-101 -548,-101 -548,-101 -542,-101 -536,-107 -536,-113 -536,-113 -536,-197 -536,-197 -536,-203 -542,-209 -548,-209 -548,-209 -688,-209 -688,-209 -694,-209 -700,-203 -700,-197 -700,-197 -700,-113 -700,-113 -700,-107 -694,-101 -688,-101"/>
<text text-anchor="middle" x="-618" y="-193.8" font-family="Times,serif" font-size="14.00">Admin::SessionsController</text>
<polyline fill="none" stroke="black" points="-700,-186 -536,-186 "/>
<text text-anchor="start" x="-692" y="-170.8" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="-692" y="-155.8" font-family="Times,serif" font-size="14.00">login</text>
<polyline fill="none" stroke="black" points="-700,-148 -536,-148 "/>
<polyline fill="none" stroke="black" points="-700,-124 -536,-124 "/>
<text text-anchor="start" x="-692" y="-108.8" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Admin::DomainVersionsController -->
<g id="node20" class="node"><title>Admin::DomainVersionsController</title>
<path fill="none" stroke="black" d="M112,-560.5C112,-560.5 298,-560.5 298,-560.5 304,-560.5 310,-566.5 310,-572.5 310,-572.5 310,-641.5 310,-641.5 310,-647.5 304,-653.5 298,-653.5 298,-653.5 112,-653.5 112,-653.5 106,-653.5 100,-647.5 100,-641.5 100,-641.5 100,-572.5 100,-572.5 100,-566.5 106,-560.5 112,-560.5"/>
<text text-anchor="middle" x="205" y="-638.3" font-family="Times,serif" font-size="14.00">Admin::DomainVersionsController</text>
<polyline fill="none" stroke="black" points="100,-630.5 310,-630.5 "/>
<text text-anchor="start" x="108" y="-615.3" font-family="Times,serif" font-size="14.00">index</text>
<polyline fill="none" stroke="black" points="100,-607.5 310,-607.5 "/>
<polyline fill="none" stroke="black" points="100,-583.5 310,-583.5 "/>
<text text-anchor="start" x="108" y="-568.3" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Admin::ContactsController -->
<g id="node21" class="node"><title>Admin::ContactsController</title>
<path fill="none" stroke="black" d="M-667.5,-680.5C-667.5,-680.5 -526.5,-680.5 -526.5,-680.5 -520.5,-680.5 -514.5,-686.5 -514.5,-692.5 -514.5,-692.5 -514.5,-791.5 -514.5,-791.5 -514.5,-797.5 -520.5,-803.5 -526.5,-803.5 -526.5,-803.5 -667.5,-803.5 -667.5,-803.5 -673.5,-803.5 -679.5,-797.5 -679.5,-791.5 -679.5,-791.5 -679.5,-692.5 -679.5,-692.5 -679.5,-686.5 -673.5,-680.5 -667.5,-680.5"/>
<text text-anchor="middle" x="-597" y="-788.3" font-family="Times,serif" font-size="14.00">Admin::ContactsController</text>
<polyline fill="none" stroke="black" points="-679.5,-780.5 -514.5,-780.5 "/>
<text text-anchor="start" x="-671.5" y="-765.3" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="-671.5" y="-750.3" font-family="Times,serif" font-size="14.00">search</text>
<polyline fill="none" stroke="black" points="-679.5,-742.5 -514.5,-742.5 "/>
<polyline fill="none" stroke="black" points="-679.5,-718.5 -514.5,-718.5 "/>
<text text-anchor="start" x="-671.5" y="-703.3" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="-671.5" y="-688.3" font-family="Times,serif" font-size="14.00">set_contact</text>
</g>
<!-- Admin::CertificatesController -->
<g id="node22" class="node"><title>Admin::CertificatesController</title>
<path fill="none" stroke="black" d="M-288,279.5C-288,279.5 -132,279.5 -132,279.5 -126,279.5 -120,273.5 -120,267.5 -120,267.5 -120,48.5 -120,48.5 -120,42.5 -126,36.5 -132,36.5 -132,36.5 -288,36.5 -288,36.5 -294,36.5 -300,42.5 -300,48.5 -300,48.5 -300,267.5 -300,267.5 -300,273.5 -294,279.5 -288,279.5"/>
<text text-anchor="middle" x="-210" y="51.7" font-family="Times,serif" font-size="14.00">Admin::CertificatesController</text>
<polyline fill="none" stroke="black" points="-300,59.5 -120,59.5 "/>
<text text-anchor="start" x="-292" y="74.7" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="-292" y="89.7" font-family="Times,serif" font-size="14.00">destroy</text>
<text text-anchor="start" x="-292" y="104.7" font-family="Times,serif" font-size="14.00">download_crt</text>
<text text-anchor="start" x="-292" y="119.7" font-family="Times,serif" font-size="14.00">download_csr</text>
<text text-anchor="start" x="-292" y="134.7" font-family="Times,serif" font-size="14.00">new</text>
<text text-anchor="start" x="-292" y="149.7" font-family="Times,serif" font-size="14.00">revoke</text>
<text text-anchor="start" x="-292" y="164.7" font-family="Times,serif" font-size="14.00">show</text>
<text text-anchor="start" x="-292" y="179.7" font-family="Times,serif" font-size="14.00">sign</text>
<polyline fill="none" stroke="black" points="-300,187.5 -120,187.5 "/>
<polyline fill="none" stroke="black" points="-300,211.5 -120,211.5 "/>
<text text-anchor="start" x="-292" y="226.7" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="-292" y="241.7" font-family="Times,serif" font-size="14.00">certificate_params</text>
<text text-anchor="start" x="-292" y="256.7" font-family="Times,serif" font-size="14.00">set_api_user</text>
<text text-anchor="start" x="-292" y="271.7" font-family="Times,serif" font-size="14.00">set_certificate</text>
</g>
<!-- Admin::BankStatementsController -->
<g id="node23" class="node"><title>Admin::BankStatementsController</title>
<path fill="none" stroke="black" d="M292,-41C292,-41 474,-41 474,-41 480,-41 486,-47 486,-53 486,-53 486,-257 486,-257 486,-263 480,-269 474,-269 474,-269 292,-269 292,-269 286,-269 280,-263 280,-257 280,-257 280,-53 280,-53 280,-47 286,-41 292,-41"/>
<text text-anchor="middle" x="383" y="-253.8" font-family="Times,serif" font-size="14.00">Admin::BankStatementsController</text>
<polyline fill="none" stroke="black" points="280,-246 486,-246 "/>
<text text-anchor="start" x="288" y="-230.8" font-family="Times,serif" font-size="14.00">bind_invoices</text>
<text text-anchor="start" x="288" y="-215.8" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="288" y="-200.8" font-family="Times,serif" font-size="14.00">create_from_import</text>
<text text-anchor="start" x="288" y="-185.8" font-family="Times,serif" font-size="14.00">download_import_file</text>
<text text-anchor="start" x="288" y="-170.8" font-family="Times,serif" font-size="14.00">import</text>
<text text-anchor="start" x="288" y="-155.8" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="288" y="-140.8" font-family="Times,serif" font-size="14.00">new</text>
<text text-anchor="start" x="288" y="-125.8" font-family="Times,serif" font-size="14.00">show</text>
<polyline fill="none" stroke="black" points="280,-118 486,-118 "/>
<polyline fill="none" stroke="black" points="280,-94 486,-94 "/>
<text text-anchor="start" x="288" y="-78.8" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="288" y="-63.8" font-family="Times,serif" font-size="14.00">bank_statement_params</text>
<text text-anchor="start" x="288" y="-48.8" font-family="Times,serif" font-size="14.00">set_bank_statement</text>
</g>
<!-- Admin::BankTransactionsController -->
<g id="node24" class="node"><title>Admin::BankTransactionsController</title>
<path fill="none" stroke="black" d="M452.5,479.5C452.5,479.5 643.5,479.5 643.5,479.5 649.5,479.5 655.5,473.5 655.5,467.5 655.5,467.5 655.5,338.5 655.5,338.5 655.5,332.5 649.5,326.5 643.5,326.5 643.5,326.5 452.5,326.5 452.5,326.5 446.5,326.5 440.5,332.5 440.5,338.5 440.5,338.5 440.5,467.5 440.5,467.5 440.5,473.5 446.5,479.5 452.5,479.5"/>
<text text-anchor="middle" x="548" y="341.7" font-family="Times,serif" font-size="14.00">Admin::BankTransactionsController</text>
<polyline fill="none" stroke="black" points="440.5,349.5 655.5,349.5 "/>
<text text-anchor="start" x="448.5" y="364.7" font-family="Times,serif" font-size="14.00">bind</text>
<text text-anchor="start" x="448.5" y="379.7" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="448.5" y="394.7" font-family="Times,serif" font-size="14.00">new</text>
<text text-anchor="start" x="448.5" y="409.7" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="440.5,417.5 655.5,417.5 "/>
<polyline fill="none" stroke="black" points="440.5,441.5 655.5,441.5 "/>
<text text-anchor="start" x="448.5" y="456.7" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="448.5" y="471.7" font-family="Times,serif" font-size="14.00">bank_transaction_params</text>
</g>
<!-- Admin::BlockedDomainsController -->
<g id="node25" class="node"><title>Admin::BlockedDomainsController</title>
<path fill="none" stroke="black" d="M152,559C152,559 340,559 340,559 346,559 352,553 352,547 352,547 352,463 352,463 352,457 346,451 340,451 340,451 152,451 152,451 146,451 140,457 140,463 140,463 140,547 140,547 140,553 146,559 152,559"/>
<text text-anchor="middle" x="246" y="466.2" font-family="Times,serif" font-size="14.00">Admin::BlockedDomainsController</text>
<polyline fill="none" stroke="black" points="140,474 352,474 "/>
<text text-anchor="start" x="148" y="489.2" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="148" y="504.2" font-family="Times,serif" font-size="14.00">index</text>
<polyline fill="none" stroke="black" points="140,512 352,512 "/>
<polyline fill="none" stroke="black" points="140,536 352,536 "/>
<text text-anchor="start" x="148" y="551.2" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Admin::DashboardsController -->
<g id="node26" class="node"><title>Admin::DashboardsController</title>
<path fill="none" stroke="black" d="M-708,39.5C-708,39.5 -550,39.5 -550,39.5 -544,39.5 -538,33.5 -538,27.5 -538,27.5 -538,-41.5 -538,-41.5 -538,-47.5 -544,-53.5 -550,-53.5 -550,-53.5 -708,-53.5 -708,-53.5 -714,-53.5 -720,-47.5 -720,-41.5 -720,-41.5 -720,27.5 -720,27.5 -720,33.5 -714,39.5 -708,39.5"/>
<text text-anchor="middle" x="-629" y="-38.3" font-family="Times,serif" font-size="14.00">Admin::DashboardsController</text>
<polyline fill="none" stroke="black" points="-720,-30.5 -538,-30.5 "/>
<text text-anchor="start" x="-712" y="-15.3" font-family="Times,serif" font-size="14.00">show</text>
<polyline fill="none" stroke="black" points="-720,-7.5 -538,-7.5 "/>
<polyline fill="none" stroke="black" points="-720,16.5 -538,16.5 "/>
<text text-anchor="start" x="-712" y="31.7" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Admin::RegistrarsController -->
<g id="node28" class="node"><title>Admin::RegistrarsController</title>
<path fill="none" stroke="black" d="M-67.5,479.5C-67.5,479.5 81.5,479.5 81.5,479.5 87.5,479.5 93.5,473.5 93.5,467.5 93.5,467.5 93.5,278.5 93.5,278.5 93.5,272.5 87.5,266.5 81.5,266.5 81.5,266.5 -67.5,266.5 -67.5,266.5 -73.5,266.5 -79.5,272.5 -79.5,278.5 -79.5,278.5 -79.5,467.5 -79.5,467.5 -79.5,473.5 -73.5,479.5 -67.5,479.5"/>
<text text-anchor="middle" x="7" y="281.7" font-family="Times,serif" font-size="14.00">Admin::RegistrarsController</text>
<polyline fill="none" stroke="black" points="-79.5,289.5 93.5,289.5 "/>
<text text-anchor="start" x="-71.5" y="304.7" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="-71.5" y="319.7" font-family="Times,serif" font-size="14.00">destroy</text>
<text text-anchor="start" x="-71.5" y="334.7" font-family="Times,serif" font-size="14.00">edit</text>
<text text-anchor="start" x="-71.5" y="349.7" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="-71.5" y="364.7" font-family="Times,serif" font-size="14.00">new</text>
<text text-anchor="start" x="-71.5" y="379.7" font-family="Times,serif" font-size="14.00">search</text>
<text text-anchor="start" x="-71.5" y="394.7" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="-79.5,402.5 93.5,402.5 "/>
<polyline fill="none" stroke="black" points="-79.5,426.5 93.5,426.5 "/>
<text text-anchor="start" x="-71.5" y="441.7" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="-71.5" y="456.7" font-family="Times,serif" font-size="14.00">registrar_params</text>
<text text-anchor="start" x="-71.5" y="471.7" font-family="Times,serif" font-size="14.00">set_registrar</text>
</g>
<!-- Admin::ReppLogsController -->
<g id="node29" class="node"><title>Admin::ReppLogsController</title>
<path fill="none" stroke="black" d="M132.5,699C132.5,699 281.5,699 281.5,699 287.5,699 293.5,693 293.5,687 293.5,687 293.5,603 293.5,603 293.5,597 287.5,591 281.5,591 281.5,591 132.5,591 132.5,591 126.5,591 120.5,597 120.5,603 120.5,603 120.5,687 120.5,687 120.5,693 126.5,699 132.5,699"/>
<text text-anchor="middle" x="207" y="606.2" font-family="Times,serif" font-size="14.00">Admin::ReppLogsController</text>
<polyline fill="none" stroke="black" points="120.5,614 293.5,614 "/>
<text text-anchor="start" x="128.5" y="629.2" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="128.5" y="644.2" font-family="Times,serif" font-size="14.00">show</text>
<polyline fill="none" stroke="black" points="120.5,652 293.5,652 "/>
<polyline fill="none" stroke="black" points="120.5,676 293.5,676 "/>
<text text-anchor="start" x="128.5" y="691.2" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Admin::InvoicesController -->
<g id="node30" class="node"><title>Admin::InvoicesController</title>
<path fill="none" stroke="black" d="M352,-560C352,-560 492,-560 492,-560 498,-560 504,-566 504,-572 504,-572 504,-716 504,-716 504,-722 498,-728 492,-728 492,-728 352,-728 352,-728 346,-728 340,-722 340,-716 340,-716 340,-572 340,-572 340,-566 346,-560 352,-560"/>
<text text-anchor="middle" x="422" y="-712.8" font-family="Times,serif" font-size="14.00">Admin::InvoicesController</text>
<polyline fill="none" stroke="black" points="340,-705 504,-705 "/>
<text text-anchor="start" x="348" y="-689.8" font-family="Times,serif" font-size="14.00">cancel</text>
<text text-anchor="start" x="348" y="-674.8" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="348" y="-659.8" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="348" y="-644.8" font-family="Times,serif" font-size="14.00">new</text>
<text text-anchor="start" x="348" y="-629.8" font-family="Times,serif" font-size="14.00">show</text>
<polyline fill="none" stroke="black" points="340,-622 504,-622 "/>
<polyline fill="none" stroke="black" points="340,-598 504,-598 "/>
<text text-anchor="start" x="348" y="-582.8" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="348" y="-567.8" font-family="Times,serif" font-size="14.00">deposit_params</text>
</g>
<!-- Admin::AdminUsersController -->
<g id="node31" class="node"><title>Admin::AdminUsersController</title>
<path fill="none" stroke="black" d="M311.5,-300.5C311.5,-300.5 474.5,-300.5 474.5,-300.5 480.5,-300.5 486.5,-306.5 486.5,-312.5 486.5,-312.5 486.5,-501.5 486.5,-501.5 486.5,-507.5 480.5,-513.5 474.5,-513.5 474.5,-513.5 311.5,-513.5 311.5,-513.5 305.5,-513.5 299.5,-507.5 299.5,-501.5 299.5,-501.5 299.5,-312.5 299.5,-312.5 299.5,-306.5 305.5,-300.5 311.5,-300.5"/>
<text text-anchor="middle" x="393" y="-498.3" font-family="Times,serif" font-size="14.00">Admin::AdminUsersController</text>
<polyline fill="none" stroke="black" points="299.5,-490.5 486.5,-490.5 "/>
<text text-anchor="start" x="307.5" y="-475.3" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="307.5" y="-460.3" font-family="Times,serif" font-size="14.00">destroy</text>
<text text-anchor="start" x="307.5" y="-445.3" font-family="Times,serif" font-size="14.00">edit</text>
<text text-anchor="start" x="307.5" y="-430.3" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="307.5" y="-415.3" font-family="Times,serif" font-size="14.00">new</text>
<text text-anchor="start" x="307.5" y="-400.3" font-family="Times,serif" font-size="14.00">show</text>
<text text-anchor="start" x="307.5" y="-385.3" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="299.5,-377.5 486.5,-377.5 "/>
<polyline fill="none" stroke="black" points="299.5,-353.5 486.5,-353.5 "/>
<text text-anchor="start" x="307.5" y="-338.3" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="307.5" y="-323.3" font-family="Times,serif" font-size="14.00">admin_user_params</text>
<text text-anchor="start" x="307.5" y="-308.3" font-family="Times,serif" font-size="14.00">set_user</text>
</g>
<!-- Admin::EppLogsController -->
<g id="node32" class="node"><title>Admin::EppLogsController</title>
<path fill="none" stroke="black" d="M-668.5,-541C-668.5,-541 -525.5,-541 -525.5,-541 -519.5,-541 -513.5,-547 -513.5,-553 -513.5,-553 -513.5,-637 -513.5,-637 -513.5,-643 -519.5,-649 -525.5,-649 -525.5,-649 -668.5,-649 -668.5,-649 -674.5,-649 -680.5,-643 -680.5,-637 -680.5,-637 -680.5,-553 -680.5,-553 -680.5,-547 -674.5,-541 -668.5,-541"/>
<text text-anchor="middle" x="-597" y="-633.8" font-family="Times,serif" font-size="14.00">Admin::EppLogsController</text>
<polyline fill="none" stroke="black" points="-680.5,-626 -513.5,-626 "/>
<text text-anchor="start" x="-672.5" y="-610.8" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="-672.5" y="-595.8" font-family="Times,serif" font-size="14.00">show</text>
<polyline fill="none" stroke="black" points="-680.5,-588 -513.5,-588 "/>
<polyline fill="none" stroke="black" points="-680.5,-564 -513.5,-564 "/>
<text text-anchor="start" x="-672.5" y="-548.8" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Admin::LegalDocumentsController -->
<g id="node33" class="node"><title>Admin::LegalDocumentsController</title>
<path fill="none" stroke="black" d="M-127.5,-580.5C-127.5,-580.5 59.5,-580.5 59.5,-580.5 65.5,-580.5 71.5,-586.5 71.5,-592.5 71.5,-592.5 71.5,-661.5 71.5,-661.5 71.5,-667.5 65.5,-673.5 59.5,-673.5 59.5,-673.5 -127.5,-673.5 -127.5,-673.5 -133.5,-673.5 -139.5,-667.5 -139.5,-661.5 -139.5,-661.5 -139.5,-592.5 -139.5,-592.5 -139.5,-586.5 -133.5,-580.5 -127.5,-580.5"/>
<text text-anchor="middle" x="-34" y="-658.3" font-family="Times,serif" font-size="14.00">Admin::LegalDocumentsController</text>
<polyline fill="none" stroke="black" points="-139.5,-650.5 71.5,-650.5 "/>
<text text-anchor="start" x="-131.5" y="-635.3" font-family="Times,serif" font-size="14.00">show</text>
<polyline fill="none" stroke="black" points="-139.5,-627.5 71.5,-627.5 "/>
<polyline fill="none" stroke="black" points="-139.5,-603.5 71.5,-603.5 "/>
<text text-anchor="start" x="-131.5" y="-588.3" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- ApplicationController -->
<g id="node34" class="node"><title>ApplicationController</title>
<path fill="none" stroke="black" d="M-467.5,-480.5C-467.5,-480.5 -344.5,-480.5 -344.5,-480.5 -338.5,-480.5 -332.5,-486.5 -332.5,-492.5 -332.5,-492.5 -332.5,-681.5 -332.5,-681.5 -332.5,-687.5 -338.5,-693.5 -344.5,-693.5 -344.5,-693.5 -467.5,-693.5 -467.5,-693.5 -473.5,-693.5 -479.5,-687.5 -479.5,-681.5 -479.5,-681.5 -479.5,-492.5 -479.5,-492.5 -479.5,-486.5 -473.5,-480.5 -467.5,-480.5"/>
<text text-anchor="middle" x="-406" y="-678.3" font-family="Times,serif" font-size="14.00">ApplicationController</text>
<polyline fill="none" stroke="black" points="-479.5,-670.5 -332.5,-670.5 "/>
<polyline fill="none" stroke="black" points="-479.5,-527.5 -332.5,-527.5 "/>
<polyline fill="none" stroke="black" points="-479.5,-503.5 -332.5,-503.5 "/>
<text text-anchor="start" x="-471.5" y="-488.3" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Registrar::DomainsController -->
<g id="node35" class="node"><title>Registrar::DomainsController</title>
<path fill="none" stroke="black" d="M292.5,279.5C292.5,279.5 465.5,279.5 465.5,279.5 471.5,279.5 477.5,273.5 477.5,267.5 477.5,267.5 477.5,18.5 477.5,18.5 477.5,12.5 471.5,6.5 465.5,6.5 465.5,6.5 292.5,6.5 292.5,6.5 286.5,6.5 280.5,12.5 280.5,18.5 280.5,18.5 280.5,267.5 280.5,267.5 280.5,273.5 286.5,279.5 292.5,279.5"/>
<text text-anchor="middle" x="379" y="21.7" font-family="Times,serif" font-size="14.00">Registrar::DomainsController</text>
<polyline fill="none" stroke="black" points="280.5,29.5 477.5,29.5 "/>
<text text-anchor="start" x="288.5" y="44.7" font-family="Times,serif" font-size="14.00">check</text>
<text text-anchor="start" x="288.5" y="59.7" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="288.5" y="74.7" font-family="Times,serif" font-size="14.00">delete</text>
<text text-anchor="start" x="288.5" y="89.7" font-family="Times,serif" font-size="14.00">destroy</text>
<text text-anchor="start" x="288.5" y="104.7" font-family="Times,serif" font-size="14.00">edit</text>
<text text-anchor="start" x="288.5" y="119.7" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="288.5" y="134.7" font-family="Times,serif" font-size="14.00">info</text>
<text text-anchor="start" x="288.5" y="149.7" font-family="Times,serif" font-size="14.00">new</text>
<text text-anchor="start" x="288.5" y="164.7" font-family="Times,serif" font-size="14.00">renew</text>
<text text-anchor="start" x="288.5" y="179.7" font-family="Times,serif" font-size="14.00">transfer</text>
<text text-anchor="start" x="288.5" y="194.7" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="280.5,202.5 477.5,202.5 "/>
<polyline fill="none" stroke="black" points="280.5,226.5 477.5,226.5 "/>
<text text-anchor="start" x="288.5" y="241.7" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="288.5" y="256.7" font-family="Times,serif" font-size="14.00">init_contacts_autocomplete_map</text>
<text text-anchor="start" x="288.5" y="271.7" font-family="Times,serif" font-size="14.00">init_domain</text>
</g>
<!-- Registrar::SessionsController -->
<g id="node37" class="node"><title>Registrar::SessionsController</title>
<path fill="none" stroke="black" d="M-288,-301C-288,-301 -136,-301 -136,-301 -130,-301 -124,-307 -124,-313 -124,-313 -124,-517 -124,-517 -124,-523 -130,-529 -136,-529 -136,-529 -288,-529 -288,-529 -294,-529 -300,-523 -300,-517 -300,-517 -300,-313 -300,-313 -300,-307 -294,-301 -288,-301"/>
<text text-anchor="middle" x="-212" y="-513.8" font-family="Times,serif" font-size="14.00">Registrar::SessionsController</text>
<polyline fill="none" stroke="black" points="-300,-506 -124,-506 "/>
<text text-anchor="start" x="-292" y="-490.8" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="-292" y="-445.8" font-family="Times,serif" font-size="14.00">id</text>
<text text-anchor="start" x="-292" y="-430.8" font-family="Times,serif" font-size="14.00">login</text>
<text text-anchor="start" x="-292" y="-415.8" font-family="Times,serif" font-size="14.00">login_mid</text>
<text text-anchor="start" x="-292" y="-400.8" font-family="Times,serif" font-size="14.00">mid</text>
<text text-anchor="start" x="-292" y="-385.8" font-family="Times,serif" font-size="14.00">mid_status</text>
<polyline fill="none" stroke="black" points="-300,-378 -124,-378 "/>
<polyline fill="none" stroke="black" points="-300,-354 -124,-354 "/>
<text text-anchor="start" x="-292" y="-338.8" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="-292" y="-308.8" font-family="Times,serif" font-size="14.00">role_base_root_url</text>
</g>
<!-- Registrar::PollsController -->
<g id="node38" class="node"><title>Registrar::PollsController</title>
<path fill="none" stroke="black" d="M-288,619.5C-288,619.5 -156,619.5 -156,619.5 -150,619.5 -144,613.5 -144,607.5 -144,607.5 -144,478.5 -144,478.5 -144,472.5 -150,466.5 -156,466.5 -156,466.5 -288,466.5 -288,466.5 -294,466.5 -300,472.5 -300,478.5 -300,478.5 -300,607.5 -300,607.5 -300,613.5 -294,619.5 -288,619.5"/>
<text text-anchor="middle" x="-222" y="481.7" font-family="Times,serif" font-size="14.00">Registrar::PollsController</text>
<polyline fill="none" stroke="black" points="-300,489.5 -144,489.5 "/>
<text text-anchor="start" x="-292" y="519.7" font-family="Times,serif" font-size="14.00">confirm_transfer</text>
<text text-anchor="start" x="-292" y="534.7" font-family="Times,serif" font-size="14.00">destroy</text>
<text text-anchor="start" x="-292" y="549.7" font-family="Times,serif" font-size="14.00">show</text>
<polyline fill="none" stroke="black" points="-300,557.5 -144,557.5 "/>
<polyline fill="none" stroke="black" points="-300,581.5 -144,581.5 "/>
<text text-anchor="start" x="-292" y="596.7" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="-292" y="611.7" font-family="Times,serif" font-size="14.00">init_epp_xml</text>
</g>
<!-- Registrar::DepositsController -->
<g id="node39" class="node"><title>Registrar::DepositsController</title>
<path fill="none" stroke="black" d="M712,-320.5C712,-320.5 864,-320.5 864,-320.5 870,-320.5 876,-326.5 876,-332.5 876,-332.5 876,-431.5 876,-431.5 876,-437.5 870,-443.5 864,-443.5 864,-443.5 712,-443.5 712,-443.5 706,-443.5 700,-437.5 700,-431.5 700,-431.5 700,-332.5 700,-332.5 700,-326.5 706,-320.5 712,-320.5"/>
<text text-anchor="middle" x="788" y="-428.3" font-family="Times,serif" font-size="14.00">Registrar::DepositsController</text>
<polyline fill="none" stroke="black" points="700,-420.5 876,-420.5 "/>
<text text-anchor="start" x="708" y="-405.3" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="708" y="-390.3" font-family="Times,serif" font-size="14.00">new</text>
<polyline fill="none" stroke="black" points="700,-382.5 876,-382.5 "/>
<polyline fill="none" stroke="black" points="700,-358.5 876,-358.5 "/>
<text text-anchor="start" x="708" y="-343.3" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="708" y="-328.3" font-family="Times,serif" font-size="14.00">deposit_params</text>
</g>
<!-- Registrar::ContactsController -->
<g id="node40" class="node"><title>Registrar::ContactsController</title>
<path fill="none" stroke="black" d="M-488,-0.5C-488,-0.5 -336,-0.5 -336,-0.5 -330,-0.5 -324,-6.5 -324,-12.5 -324,-12.5 -324,-201.5 -324,-201.5 -324,-207.5 -330,-213.5 -336,-213.5 -336,-213.5 -488,-213.5 -488,-213.5 -494,-213.5 -500,-207.5 -500,-201.5 -500,-201.5 -500,-12.5 -500,-12.5 -500,-6.5 -494,-0.5 -488,-0.5"/>
<text text-anchor="middle" x="-412" y="-198.3" font-family="Times,serif" font-size="14.00">Registrar::ContactsController</text>
<polyline fill="none" stroke="black" points="-500,-190.5 -324,-190.5 "/>
<text text-anchor="start" x="-492" y="-175.3" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="-492" y="-160.3" font-family="Times,serif" font-size="14.00">delete</text>
<text text-anchor="start" x="-492" y="-145.3" font-family="Times,serif" font-size="14.00">destroy</text>
<text text-anchor="start" x="-492" y="-130.3" font-family="Times,serif" font-size="14.00">edit</text>
<text text-anchor="start" x="-492" y="-115.3" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="-492" y="-100.3" font-family="Times,serif" font-size="14.00">new</text>
<text text-anchor="start" x="-492" y="-85.3" font-family="Times,serif" font-size="14.00">show</text>
<text text-anchor="start" x="-492" y="-70.3" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="-500,-62.5 -324,-62.5 "/>
<polyline fill="none" stroke="black" points="-500,-38.5 -324,-38.5 "/>
<text text-anchor="start" x="-492" y="-23.3" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="-492" y="-8.3" font-family="Times,serif" font-size="14.00">init_epp_contact</text>
</g>
<!-- Registrar::DeppController -->
<g id="node41" class="node"><title>Registrar::DeppController</title>
<path fill="none" stroke="black" d="M152,-701C152,-701 286,-701 286,-701 292,-701 298,-707 298,-713 298,-713 298,-827 298,-827 298,-833 292,-839 286,-839 286,-839 152,-839 152,-839 146,-839 140,-833 140,-827 140,-827 140,-713 140,-713 140,-707 146,-701 152,-701"/>
<text text-anchor="middle" x="219" y="-823.8" font-family="Times,serif" font-size="14.00">Registrar::DeppController</text>
<polyline fill="none" stroke="black" points="140,-816 298,-816 "/>
<text text-anchor="start" x="148" y="-800.8" font-family="Times,serif" font-size="14.00">authenticate_user</text>
<text text-anchor="start" x="148" y="-785.8" font-family="Times,serif" font-size="14.00">depp_controller?</text>
<text text-anchor="start" x="148" y="-770.8" font-family="Times,serif" font-size="14.00">depp_current_user</text>
<text text-anchor="start" x="148" y="-755.8" font-family="Times,serif" font-size="14.00">response_ok?</text>
<polyline fill="none" stroke="black" points="140,-748 298,-748 "/>
<polyline fill="none" stroke="black" points="140,-724 298,-724 "/>
<text text-anchor="start" x="148" y="-708.8" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Registrar::NameserversController -->
<g id="node42" class="node"><title>Registrar::NameserversController</title>
<path fill="none" stroke="black" d="M-688,699C-688,699 -512,699 -512,699 -506,699 -500,693 -500,687 -500,687 -500,617 -500,617 -500,611 -506,605 -512,605 -512,605 -688,605 -688,605 -694,605 -700,611 -700,617 -700,617 -700,687 -700,687 -700,693 -694,699 -688,699"/>
<text text-anchor="middle" x="-600" y="620.2" font-family="Times,serif" font-size="14.00">Registrar::NameserversController</text>
<polyline fill="none" stroke="black" points="-700,628 -500,628 "/>
<polyline fill="none" stroke="black" points="-700,652 -500,652 "/>
<polyline fill="none" stroke="black" points="-700,676 -500,676 "/>
<text text-anchor="start" x="-692" y="691.2" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Registrar::XmlConsolesController -->
<g id="node43" class="node"><title>Registrar::XmlConsolesController</title>
<path fill="none" stroke="black" d="M391.5,639.5C391.5,639.5 570.5,639.5 570.5,639.5 576.5,639.5 582.5,633.5 582.5,627.5 582.5,627.5 582.5,528.5 582.5,528.5 582.5,522.5 576.5,516.5 570.5,516.5 570.5,516.5 391.5,516.5 391.5,516.5 385.5,516.5 379.5,522.5 379.5,528.5 379.5,528.5 379.5,627.5 379.5,627.5 379.5,633.5 385.5,639.5 391.5,639.5"/>
<text text-anchor="middle" x="481" y="531.7" font-family="Times,serif" font-size="14.00">Registrar::XmlConsolesController</text>
<polyline fill="none" stroke="black" points="379.5,539.5 582.5,539.5 "/>
<text text-anchor="start" x="387.5" y="554.7" font-family="Times,serif" font-size="14.00">create</text>
<text text-anchor="start" x="387.5" y="569.7" font-family="Times,serif" font-size="14.00">load_xml</text>
<text text-anchor="start" x="387.5" y="584.7" font-family="Times,serif" font-size="14.00">show</text>
<polyline fill="none" stroke="black" points="379.5,592.5 582.5,592.5 "/>
<polyline fill="none" stroke="black" points="379.5,616.5 582.5,616.5 "/>
<text text-anchor="start" x="387.5" y="631.7" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Registrar::InvoicesController -->
<g id="node44" class="node"><title>Registrar::InvoicesController</title>
<path fill="none" stroke="black" d="M532.5,80C532.5,80 683.5,80 683.5,80 689.5,80 695.5,74 695.5,68 695.5,68 695.5,-76 695.5,-76 695.5,-82 689.5,-88 683.5,-88 683.5,-88 532.5,-88 532.5,-88 526.5,-88 520.5,-82 520.5,-76 520.5,-76 520.5,68 520.5,68 520.5,74 526.5,80 532.5,80"/>
<text text-anchor="middle" x="608" y="-72.8" font-family="Times,serif" font-size="14.00">Registrar::InvoicesController</text>
<polyline fill="none" stroke="black" points="520.5,-65 695.5,-65 "/>
<text text-anchor="start" x="528.5" y="-49.8" font-family="Times,serif" font-size="14.00">cancel</text>
<text text-anchor="start" x="528.5" y="-34.8" font-family="Times,serif" font-size="14.00">download_pdf</text>
<text text-anchor="start" x="528.5" y="-19.8" font-family="Times,serif" font-size="14.00">forward</text>
<text text-anchor="start" x="528.5" y="-4.8" font-family="Times,serif" font-size="14.00">index</text>
<text text-anchor="start" x="528.5" y="10.2" font-family="Times,serif" font-size="14.00">show</text>
<polyline fill="none" stroke="black" points="520.5,18 695.5,18 "/>
<polyline fill="none" stroke="black" points="520.5,42 695.5,42 "/>
<text text-anchor="start" x="528.5" y="57.2" font-family="Times,serif" font-size="14.00">_layout</text>
<text text-anchor="start" x="528.5" y="72.2" font-family="Times,serif" font-size="14.00">set_invoice</text>
</g>
<!-- Registrar::AccountActivitiesController -->
<g id="node45" class="node"><title>Registrar::AccountActivitiesController</title>
<path fill="none" stroke="black" d="M-547.5,559.5C-547.5,559.5 -344.5,559.5 -344.5,559.5 -338.5,559.5 -332.5,553.5 -332.5,547.5 -332.5,547.5 -332.5,478.5 -332.5,478.5 -332.5,472.5 -338.5,466.5 -344.5,466.5 -344.5,466.5 -547.5,466.5 -547.5,466.5 -553.5,466.5 -559.5,472.5 -559.5,478.5 -559.5,478.5 -559.5,547.5 -559.5,547.5 -559.5,553.5 -553.5,559.5 -547.5,559.5"/>
<text text-anchor="middle" x="-446" y="481.7" font-family="Times,serif" font-size="14.00">Registrar::AccountActivitiesController</text>
<polyline fill="none" stroke="black" points="-559.5,489.5 -332.5,489.5 "/>
<text text-anchor="start" x="-551.5" y="504.7" font-family="Times,serif" font-size="14.00">index</text>
<polyline fill="none" stroke="black" points="-559.5,512.5 -332.5,512.5 "/>
<polyline fill="none" stroke="black" points="-559.5,536.5 -332.5,536.5 "/>
<text text-anchor="start" x="-551.5" y="551.7" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Registrant::DomainsController -->
<g id="node46" class="node"><title>Registrant::DomainsController</title>
<path fill="none" stroke="black" d="M-68.5,-720.5C-68.5,-720.5 92.5,-720.5 92.5,-720.5 98.5,-720.5 104.5,-726.5 104.5,-732.5 104.5,-732.5 104.5,-801.5 104.5,-801.5 104.5,-807.5 98.5,-813.5 92.5,-813.5 92.5,-813.5 -68.5,-813.5 -68.5,-813.5 -74.5,-813.5 -80.5,-807.5 -80.5,-801.5 -80.5,-801.5 -80.5,-732.5 -80.5,-732.5 -80.5,-726.5 -74.5,-720.5 -68.5,-720.5"/>
<text text-anchor="middle" x="12" y="-798.3" font-family="Times,serif" font-size="14.00">Registrant::DomainsController</text>
<polyline fill="none" stroke="black" points="-80.5,-790.5 104.5,-790.5 "/>
<text text-anchor="start" x="-72.5" y="-775.3" font-family="Times,serif" font-size="14.00">index</text>
<polyline fill="none" stroke="black" points="-80.5,-767.5 104.5,-767.5 "/>
<polyline fill="none" stroke="black" points="-80.5,-743.5 104.5,-743.5 "/>
<text text-anchor="start" x="-72.5" y="-728.3" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Registrant::SessionsController -->
<g id="node47" class="node"><title>Registrant::SessionsController</title>
<path fill="none" stroke="black" d="M532,-120C532,-120 690,-120 690,-120 696,-120 702,-126 702,-132 702,-132 702,-276 702,-276 702,-282 696,-288 690,-288 690,-288 532,-288 532,-288 526,-288 520,-282 520,-276 520,-276 520,-132 520,-132 520,-126 526,-120 532,-120"/>
<text text-anchor="middle" x="611" y="-272.8" font-family="Times,serif" font-size="14.00">Registrant::SessionsController</text>
<polyline fill="none" stroke="black" points="520,-265 702,-265 "/>
<text text-anchor="start" x="528" y="-249.8" font-family="Times,serif" font-size="14.00">find_user_by_idc</text>
<text text-anchor="start" x="528" y="-234.8" font-family="Times,serif" font-size="14.00">id</text>
<text text-anchor="start" x="528" y="-219.8" font-family="Times,serif" font-size="14.00">login</text>
<text text-anchor="start" x="528" y="-204.8" font-family="Times,serif" font-size="14.00">login_mid</text>
<text text-anchor="start" x="528" y="-189.8" font-family="Times,serif" font-size="14.00">mid</text>
<text text-anchor="start" x="528" y="-174.8" font-family="Times,serif" font-size="14.00">mid_status</text>
<polyline fill="none" stroke="black" points="520,-167 702,-167 "/>
<polyline fill="none" stroke="black" points="520,-143 702,-143 "/>
<text text-anchor="start" x="528" y="-127.8" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Registrant::DomainUpdateConfirmsController -->
<g id="node48" class="node"><title>Registrant::DomainUpdateConfirmsController</title>
<path fill="none" stroke="black" d="M152,419C152,419 398,419 398,419 404,419 410,413 410,407 410,407 410,323 410,323 410,317 404,311 398,311 398,311 152,311 152,311 146,311 140,317 140,323 140,323 140,407 140,407 140,413 146,419 152,419"/>
<text text-anchor="middle" x="275" y="326.2" font-family="Times,serif" font-size="14.00">Registrant::DomainUpdateConfirmsController</text>
<polyline fill="none" stroke="black" points="140,334 410,334 "/>
<text text-anchor="start" x="148" y="349.2" font-family="Times,serif" font-size="14.00">show</text>
<text text-anchor="start" x="148" y="364.2" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="140,372 410,372 "/>
<polyline fill="none" stroke="black" points="140,396 410,396 "/>
<text text-anchor="start" x="148" y="411.2" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Registrant::WhoisController -->
<g id="node49" class="node"><title>Registrant::WhoisController</title>
<path fill="none" stroke="black" d="M-687.5,179.5C-687.5,179.5 -540.5,179.5 -540.5,179.5 -534.5,179.5 -528.5,173.5 -528.5,167.5 -528.5,167.5 -528.5,98.5 -528.5,98.5 -528.5,92.5 -534.5,86.5 -540.5,86.5 -540.5,86.5 -687.5,86.5 -687.5,86.5 -693.5,86.5 -699.5,92.5 -699.5,98.5 -699.5,98.5 -699.5,167.5 -699.5,167.5 -699.5,173.5 -693.5,179.5 -687.5,179.5"/>
<text text-anchor="middle" x="-614" y="101.7" font-family="Times,serif" font-size="14.00">Registrant::WhoisController</text>
<polyline fill="none" stroke="black" points="-699.5,109.5 -528.5,109.5 "/>
<text text-anchor="start" x="-691.5" y="124.7" font-family="Times,serif" font-size="14.00">index</text>
<polyline fill="none" stroke="black" points="-699.5,132.5 -528.5,132.5 "/>
<polyline fill="none" stroke="black" points="-699.5,156.5 -528.5,156.5 "/>
<text text-anchor="start" x="-691.5" y="171.7" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
<!-- Registrant::DomainDeleteConfirmsController -->
<g id="node50" class="node"><title>Registrant::DomainDeleteConfirmsController</title>
<path fill="none" stroke="black" d="M-408,419C-408,419 -166,419 -166,419 -160,419 -154,413 -154,407 -154,407 -154,323 -154,323 -154,317 -160,311 -166,311 -166,311 -408,311 -408,311 -414,311 -420,317 -420,323 -420,323 -420,407 -420,407 -420,413 -414,419 -408,419"/>
<text text-anchor="middle" x="-287" y="326.2" font-family="Times,serif" font-size="14.00">Registrant::DomainDeleteConfirmsController</text>
<polyline fill="none" stroke="black" points="-420,334 -154,334 "/>
<text text-anchor="start" x="-412" y="349.2" font-family="Times,serif" font-size="14.00">show</text>
<text text-anchor="start" x="-412" y="364.2" font-family="Times,serif" font-size="14.00">update</text>
<polyline fill="none" stroke="black" points="-420,372 -154,372 "/>
<polyline fill="none" stroke="black" points="-420,396 -154,396 "/>
<text text-anchor="start" x="-412" y="411.2" font-family="Times,serif" font-size="14.00">_layout</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 116 KiB

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 209 KiB

View file

@ -1,11 +0,0 @@
--- mod_epp.h 2015-03-27 15:30:20.027130050 +0200
+++ mod_epp_new.h 2015-03-27 15:30:38.499130269 +0200
@@ -60,7 +60,7 @@
#endif
#define EPP_TCP_HEADER_SIZE 4 /* just one longword */
-#define EPP_MAX_FRAME_SIZE 65536 /* don't accept larger xml data blocks */
+#define EPP_MAX_FRAME_SIZE 15728640 /* don't accept larger xml data blocks (8MB + 30% base64 + xml + savings)*/
#define TRIDSIZE 128 /* actually, it should be 3 to 64 chars,
but due to unicode we'll give it more room. */

View file

@ -1,37 +0,0 @@
mod_epp.c | 2 +-
mod_epp.h | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/mod_epp.c b/mod_epp.c
index 8b1ba6f..66e46d8 100644
--- a/mod_epp.c
+++ b/mod_epp.c
@@ -756,7 +756,7 @@ sprintf(content_length, "%lu", strlen(EPP_CONTENT_FRAME_CGI)
strlen(conf->raw_frame)
+ er->orig_xml_size) : 0));
-apr_table_set(r->headers_in, "Content-Type", "multipart/form-data; boundary=--BOUNDARY--");
+apr_table_set(r->headers_in, "Content-Type", EPP_CONTENT_TYPE_CGI);
apr_table_set(r->headers_in, "Content-Length", content_length);
apr_table_set(r->headers_in, "Cookie", er->ur->cookie);
diff --git a/mod_epp.h b/mod_epp.h
index e72d980..5e99bad 100644
--- a/mod_epp.h
+++ b/mod_epp.h
@@ -96,10 +96,10 @@ module AP_MODULE_DECLARE_DATA epp_module;
#define EPP_DEFAULT_RC_HEADER "X-EPP-Returncode"
-#define EPP_CONTENT_TYPE_CGI "multipart/form-data; boundary=--BOUNDARY--"
-#define EPP_CONTENT_FRAME_CGI "----BOUNDARY--\r\nContent-Disposition: form-data; name=\"frame\"\r\n\r\n"
-#define EPP_CONTENT_RAW_CGI "\r\n----BOUNDARY--\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n"
-#define EPP_CONTENT_CLTRID_CGI "\r\n----BOUNDARY--\r\nContent-Disposition: form-data; name=\"clTRID\"\r\n\r\n"
+#define EPP_CONTENT_TYPE_CGI "multipart/form-data; boundary=--BOUNDARY"
+#define EPP_CONTENT_FRAME_CGI "----BOUNDARY\r\nContent-Disposition: form-data; name=\"frame\"\r\n\r\n"
+#define EPP_CONTENT_RAW_CGI "\r\n----BOUNDARY\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n"
+#define EPP_CONTENT_CLTRID_CGI "\r\n----BOUNDARY\r\nContent-Disposition: form-data; name=\"clTRID\"\r\n\r\n"
#define EPP_CONTENT_POSTFIX_CGI "\r\n----BOUNDARY--\r\n"
/*

View file

@ -0,0 +1,34 @@
## GET /api/v1/registrant/companies
Returns list of companies registered in business register for the current registrant.
#### Parameters
| Field name | Required | Type | Allowed values | Description |
| ---------- | -------- | ---- | -------------- | ----------- |
| limit | false | Integer | [1..200] | How many companies to show |
| offset | false | Integer | | Company number to start at |
#### Request
```
GET /api/v1/registrant/companies?limit=1 HTTP/1.1
Accept: application/json
Authorization: Bearer Z2l0bGFiOmdoeXQ5ZTRmdQ==
Content-Type: application/json
```
#### Response
```
HTTP/1.1 200
Content-Type: application/json
{
"companies":[
{
"name":"ACME Ltd",
"registry_no":"37605030299",
"country_code":"EE"
}
]
}
```

View file

@ -1,4 +1,4 @@
Testing
Testing local project without docker container
-------
Setup test databases:
@ -10,108 +10,17 @@ Run basic test (no EPP tests):
rake
Testing EPP
===========
Testing using docker container
-------
In order to test EPP, you have to configure apache to handle EPP request correctly.
It's strongly recommended to test/debug registry application using docker containers from https://github.com/internetee/docker-images .
For doing so first setup containers as per docker images documentation (https://github.com/internetee/docker-images/blob/master/README.MD), then in docker images directory run the following:
### Apache site config
docker-compose run registry bundle exec rake RAILS_ENV=test COVERAGE=true
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
<IfModule mod_epp.c>
Listen 701
<VirtualHost *: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
</VirtualHost>
</IfModule>
```
* 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
<IfModule mod_epp.c>
<Directory "/usr/lib/cgi-bin/epp">
Options ExecCGI
SetHandler cgi-script
</Directory>
Listen 1700
<VirtualHost *: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
<Location /epp/auth>
AuthType Basic
AuthName "EPP"
AuthUserFile /etc/apache2/htpasswd
require valid-user
</Location>
</VirtualHost>
</IfModule>
```
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
To run single test:
docker-compose run registry bundle exec rails test <path_to_test> RAILS_ENV=test COVERAGE=true
Allowed testing email list
==========================

View file

@ -1,7 +0,0 @@
module Devise
module Models
# Devise fails without this module (and model: false does not help)
module IdCardAuthenticatable
end
end
end

View file

@ -1,49 +0,0 @@
module Devise
module Strategies
class IdCardAuthenticatable < Devise::Strategies::Authenticatable
def valid?
env['SSL_CLIENT_S_DN_CN'].present?
end
def authenticate!
resource = mapping.to
user = resource.find_by_id_card(id_card)
if user
success!(user)
else
fail
end
end
private
def id_card
id_card = IdCard.new
id_card.first_name = first_name
id_card.last_name = last_name
id_card.personal_code = personal_code
id_card.country_code = country_code
id_card
end
def first_name
env['SSL_CLIENT_S_DN_CN'].split(',').second.force_encoding('utf-8')
end
def last_name
env['SSL_CLIENT_S_DN_CN'].split(',').first.force_encoding('utf-8')
end
def personal_code
env['SSL_CLIENT_S_DN_CN'].split(',').last
end
def country_code
env['SSL_CLIENT_I_DN_C']
end
end
end
end
Warden::Strategies.add(:id_card_authenticatable, Devise::Strategies::IdCardAuthenticatable)

View file

@ -0,0 +1,20 @@
module Serializers
module RegistrantApi
class Company
attr_reader :company, :country_code
def initialize(company:, country_code:)
@company = company
@country_code = country_code
end
def to_json(*_args)
{
name: company.company_name,
registry_no: company.registration_number,
country_code: @country_code,
}
end
end
end
end

View file

@ -23,6 +23,9 @@ namespace :invoices do
end
if incoming_transactions.any?
log 'Got incoming transactions'
log incoming_transactions
bank_statement = BankStatement.new(bank_code: Setting.registry_bank_code,
iban: Setting.registry_iban)
@ -41,8 +44,15 @@ namespace :invoices do
transaction.autobind_invoice
end
end
else
log 'Got no incoming transactions parsed, aborting'
end
puts "Transactions processed: #{incoming_transactions.size}"
end
def log(msg)
@log ||= Logger.new(STDOUT)
@log.info(msg)
end
end

View file

@ -78,6 +78,18 @@ identical_to_william:
auth_info: 5ab865
uuid: c0a191d5-3793-4f0b-8f85-491612d0293e
registrar_ltd:
name: Registrar Ltd
email: registrar@inbox.test
phone: '+555.555'
ident: 1234567890
ident_type: org
registrar: goodnames
ident_country_code: US
code: registrarltd-001
auth_info: e2c441
uuid: 28b65455-6f1a-49fd-961c-0758886dbd76
invalid:
name: any
code: invalid

View file

@ -0,0 +1,44 @@
$VERBOSE=nil
require 'test_helper'
require 'auth_token/auth_token_creator'
class RegistrantApiCompaniesTest < ApplicationIntegrationTest
def setup
super
@contact = contacts(:john)
@user = users(:registrant)
@auth_headers = { 'HTTP_AUTHORIZATION' => auth_token }
end
def test_accepts_limit_and_offset_parameters
contacts(:william).update!(ident: '1234', ident_type: 'priv', ident_country_code: 'US')
get '/api/v1/registrant/companies', params: { 'limit' => 1, 'offset' => 0 },
headers: @auth_headers
response_json = JSON.parse(response.body, symbolize_names: true)
assert_equal(200, response.status)
assert_equal(1, response_json.values.flatten.count)
get '/api/v1/registrant/companies', headers: @auth_headers
response_json = JSON.parse(response.body, symbolize_names: true)
assert_equal(@user.companies.size, response_json.count)
end
def test_format
contacts(:william).update!(ident: '1234', ident_type: 'priv', ident_country_code: 'US')
get '/api/v1/registrant/companies', headers: @auth_headers
response_json = JSON.parse(response.body, symbolize_names: true)
assert_equal(1, response_json.count)
assert response_json.is_a?(Hash)
assert_equal(:companies, response_json.keys.first)
end
private
def auth_token
token_creator = AuthTokenCreator.create_with_defaults(@user)
hash = token_creator.token_in_hash
"Bearer #{hash[:access_token]}"
end
end

View file

@ -12,7 +12,7 @@ class RegistrantApiContactsTest < ApplicationIntegrationTest
def test_root_accepts_limit_and_offset_parameters
contacts(:william).update!(ident: '1234', ident_type: 'priv', ident_country_code: 'US')
assert_equal 4, @user.contacts.size
assert_equal 4, @user.contacts(representable: false).size
get '/api/v1/registrant/contacts', params: { 'limit' => 1, 'offset' => 0 },
headers: @auth_headers
@ -22,7 +22,7 @@ class RegistrantApiContactsTest < ApplicationIntegrationTest
get '/api/v1/registrant/contacts', headers: @auth_headers
response_json = JSON.parse(response.body, symbolize_names: true)
assert_equal(@user.contacts.size, response_json.count)
assert_equal(@user.contacts(representable: false).size, response_json.count)
end
def test_get_contact_details_by_uuid

View file

@ -35,7 +35,7 @@ class RegistrantApiV1ContactListTest < ActionDispatch::IntegrationTest
get api_v1_registrant_contacts_path, as: :json, headers: { 'HTTP_AUTHORIZATION' => auth_token }
response_json = JSON.parse(response.body, symbolize_names: true)
assert_equal @user.contacts.count, response_json.size
assert_equal @user.contacts(representable: false).count, response_json.size
assert_includes response_json.map{ |hash| hash[:code] }, @contact.code
end

View file

@ -167,4 +167,36 @@ class EppDomainRenewBaseTest < EppTestCase
end
assert_epp_response :parameter_value_policy_error
end
def test_fails_if_domain_has_renewal_prohibited_statuses
travel_to Time.zone.parse('2010-07-05')
domain = domains(:shop)
domain.statuses << DomainStatus::SERVER_RENEW_PROHIBITED
domain.save
original_valid_to = domain.valid_to
default_renewal_period = 1.year
request_xml = <<-XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
<command>
<renew>
<domain:renew xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
<domain:name>#{domain.name}</domain:name>
<domain:curExpDate>#{domain.expire_time.to_date}</domain:curExpDate>
<domain:period unit="y">1</domain:period>
</domain:renew>
</renew>
</command>
</epp>
XML
post epp_renew_path, params: { frame: request_xml },
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
domain.reload
assert_epp_response :object_status_prohibits_operation
assert_equal original_valid_to, domain.valid_to
end
end

View file

@ -31,7 +31,7 @@ class EppLoginCredentialsTest < EppTestCase
end
def test_already_logged_in
assert true # Handled by mod_epp
assert true # Handled by EPP proxy
end
def test_wrong_credentials

View file

@ -1,31 +0,0 @@
require 'test_helper'
class RegistrantAreaIdCardSignInTest < ApplicationIntegrationTest
setup do
allow_business_registry_component_reach_server
end
def test_succeeds
post registrant_id_card_sign_in_path, headers: { 'SSL_CLIENT_S_DN_CN' => 'DOE,JOHN,1234',
'SSL_CLIENT_I_DN_C' => 'US' }
follow_redirect!
assert_response :ok
assert_equal registrant_root_path, path
assert_not_nil controller.current_registrant_user
end
def test_fails_when_certificate_is_absent
post registrant_id_card_sign_in_path, headers: { 'SSL_CLIENT_S_DN_CN' => '' }
assert_response :ok
assert_equal registrant_id_card_sign_in_path, path
assert_nil controller.current_registrant_user
end
private
def allow_business_registry_component_reach_server
WebMock.allow_net_connect!
end
end

View file

@ -1,65 +0,0 @@
require 'test_helper'
class RegistrarAreaIdCardSignInTest < ApplicationIntegrationTest
setup do
@user = users(:api_bestnames)
@original_registrar_area_ip_whitelist = Setting.registrar_ip_whitelist_enabled
end
teardown do
Setting.registrar_ip_whitelist_enabled = @original_registrar_area_ip_whitelist
end
def test_signs_in_a_user_when_id_card_owner_is_found
assert_equal '1234', @user.identity_code
post registrar_id_card_sign_in_path, headers: { 'SSL_CLIENT_S_DN_CN' => 'DOE,JOHN,1234' }
follow_redirect!
assert_response :ok
assert_equal registrar_root_path, path
assert_not_nil controller.current_registrar_user
end
def test_does_not_sign_in_a_user_when_id_card_owner_is_not_found
post registrar_id_card_sign_in_path,
headers: { 'SSL_CLIENT_S_DN_CN' => 'DOE,JOHN,unacceptable-personal-code' }
assert_nil controller.current_registrar_user
assert_equal registrar_id_card_sign_in_path, path
assert_includes response.body, 'Failed to Login'
end
def test_does_not_sign_in_a_user_when_id_card_owner_is_found_but_ip_is_not_allowed
allow_access_to_sign_in_page
assert_equal '127.0.0.1', white_ips(:one).ipv4
assert_equal '1234', @user.identity_code
Setting.registrar_ip_whitelist_enabled = true
post registrar_id_card_sign_in_path, headers: { 'SSL_CLIENT_S_DN_CN' => 'DOE,JOHN,1234',
'REMOTE_ADDR' => '127.0.0.2' }
assert_equal registrar_id_card_sign_in_path, path
assert_equal 'Access denied from IP 127.0.0.2', response.body
get registrar_root_path
assert_redirected_to new_registrar_user_session_path
end
def test_does_not_sign_in_a_user_when_certificate_is_absent
post registrar_id_card_sign_in_path, headers: { 'SSL_CLIENT_S_DN_CN' => '' }
assert_nil controller.current_registrar_user
assert_equal registrar_id_card_sign_in_path, path
end
private
def allow_access_to_sign_in_page
another_registrar_white_ip = white_ips(:one).dup
another_registrar_white_ip.ipv4 = '127.0.0.2'
another_registrar_white_ip.registrar = registrars(:goodnames)
another_registrar_white_ip.save!
end
end

View file

@ -1,13 +0,0 @@
require 'test_helper'
class IdCardAuthenticatableTest < ActiveSupport::TestCase
def test_valid_when_id_card_data_is_present_in_env
strategy = Devise::Strategies::IdCardAuthenticatable.new({ 'SSL_CLIENT_S_DN_CN' => 'some' })
assert strategy.valid?
end
def test_not_valid_when_id_card_data_is_absent_in_env
strategy = Devise::Strategies::IdCardAuthenticatable.new({})
assert_not strategy.valid?
end
end

View file

@ -73,7 +73,7 @@ class DomainDeleteMailerTest < ActionMailer::TestCase
assert_emails 1
assert_equal ['legal@registry.test'], email.from
assert_equal @domain.force_delete_contact_emails, email.to
assert @domain.force_delete_contact_emails.sort == email.to.sort
assert_equal 'Domeen shop.test on kustutusmenetluses' \
' / Domain shop.test is in deletion process' \
' / Домен shop.test в процессе удаления', email.subject

View file

@ -52,17 +52,6 @@ class ApiUserTest < ActiveSupport::TestCase
assert ApiUser.new.active?
end
def test_finds_user_by_id_card
id_card = IdCard.new
id_card.personal_code = 'one'
@user.update!(identity_code: 'one')
assert_equal @user, ApiUser.find_by_id_card(id_card)
@user.update!(identity_code: 'another')
assert_nil ApiUser.find_by_id_card(id_card)
end
def test_verifies_pki_status
certificate = certificates(:api)

View file

@ -242,4 +242,14 @@ class NewDomainForceDeleteTest < ActiveSupport::TestCase
assert_not_includes(@domain.statuses, asserted_status)
end
def test_force_delete_does_not_affect_pending_update_check
@domain.schedule_force_delete(type: :soft)
@domain.reload
@domain.statuses << DomainStatus::PENDING_UPDATE
assert @domain.force_delete_scheduled?
assert @domain.pending_update?
end
end

View file

@ -39,6 +39,21 @@ class DomainCronTest < ActiveSupport::TestCase
assert_emails 1
end
def does_not_deliver_forced_email_if_template_empty
Setting.redemption_grace_period = 30
@domain.update(valid_to: Time.zone.parse('2012-08-05'))
assert_not @domain.force_delete_scheduled?
travel_to Time.zone.parse('2010-07-05')
@domain.schedule_force_delete(type: :soft)
@domain.reload
@domain.update(template_name: nil)
travel_to Time.zone.parse('2010-08-06')
DomainCron.start_client_hold
assert_emails 0
end
def test_does_not_sets_hold_if_already_set
Setting.redemption_grace_period = 30
@ -52,4 +67,26 @@ class DomainCronTest < ActiveSupport::TestCase
assert_emails 0
end
def test_cleans_expired_pendings_when_force_delete_active
Setting.expire_pending_confirmation = 0
# Set force delete
@domain.schedule_force_delete(type: :soft)
@domain.reload
@domain.statuses << DomainStatus::PENDING_UPDATE
# Set domain registrant change that's expired
@domain.update!(registrant_verification_asked_at: Time.zone.now,
registrant_verification_token: 'test',
statuses: @domain.statuses)
assert @domain.pending_update?
@domain.reload
DomainCron.clean_expired_pendings
@domain.reload
assert_not @domain.pending_update?
end
end

View file

@ -431,6 +431,19 @@ class DomainTest < ActiveSupport::TestCase
assert_equal created_at, domain.registered_at
end
def test_not_renewable_if_renew_prohibited
assert @domain.renewable?
@domain.statuses << DomainStatus::SERVER_RENEW_PROHIBITED
assert_not @domain.renewable?
@domain.statuses.delete(DomainStatus::SERVER_RENEW_PROHIBITED)
assert @domain.renewable?
@domain.statuses << DomainStatus::CLIENT_RENEW_PROHIBITED
assert_not @domain.renewable?
end
private
def valid_domain

View file

@ -26,13 +26,4 @@ class RegistrantUserCreationTest < ActiveSupport::TestCase
user = User.find_by(registrant_ident: 'EE-37710100070')
assert_equal('JOHN SMITH', user.username)
end
def test_find_or_create_by_mid_data_creates_a_user
user_data = OpenStruct.new(user_country: 'EE', user_id_code: '37710100070',
user_givenname: 'JOHN', user_surname: 'SMITH')
RegistrantUser.find_or_create_by_mid_data(user_data)
user = User.find_by(registrant_ident: 'EE-37710100070')
assert_equal('JOHN SMITH', user.username)
end
end

View file

@ -30,34 +30,6 @@ class RegistrantUserTest < ActiveSupport::TestCase
assert_equal Country.new('US'), user.country
end
def test_finding_by_id_card_creates_new_user_upon_first_sign_in
assert_not_equal 'US-5555', @user.registrant_ident
id_card = IdCard.new
id_card.first_name = 'John'
id_card.last_name = 'Doe'
id_card.personal_code = '5555'
id_card.country_code = 'US'
assert_difference 'RegistrantUser.count' do
RegistrantUser.find_by_id_card(id_card)
end
user = RegistrantUser.last
assert_equal 'US-5555', user.registrant_ident
assert_equal 'John Doe', user.username
end
def test_finding_by_id_card_reuses_existing_user_upon_subsequent_id_card_sign_ins
@user.update!(registrant_ident: 'US-5555')
id_card = IdCard.new
id_card.personal_code = '5555'
id_card.country_code = 'US'
assert_no_difference 'RegistrantUser.count' do
RegistrantUser.find_by_id_card(id_card)
end
end
def test_queries_company_register_for_associated_companies
assert_equal 'US-1234', @user.registrant_ident
@ -92,4 +64,4 @@ class RegistrantUserTest < ActiveSupport::TestCase
assert_equal %w(shop airport), @user.administered_domains
end
end
end
end

View file

@ -28,6 +28,20 @@ class RegistrantAreaDomainListTest < ApplicationSystemTestCase
assert_no_text 'metro.test'
end
def test_only_shows_direct_relation_and_or_company_domains
# case https://github.com/internetee/registry/issues/1690
tech_contact = contacts(:registrar_ltd)
# All domains share the same tech contact object
Domain.all.each do |domain|
DomainContact.create(domain: domain, contact: tech_contact, type: TechDomainContact)
end
visit registrant_domains_url
assert_no_text 'Company register is unavailable.'
assert_no_text 'metro.test'
end
def test_notification_when_company_register_is_unavailable
CompanyRegister::Client.stub(:new, CompanyRegisterClientStub.new) do
visit registrant_domains_url
@ -54,4 +68,4 @@ class RegistrantAreaDomainListTest < ApplicationSystemTestCase
assert_text 'shop.test'
end
end
end

View file

@ -0,0 +1,51 @@
require 'application_system_test_case'
class RegistrantAreaTaraUsersTest < ApplicationSystemTestCase
def setup
super
OmniAuth.config.test_mode = true
@registrant = users(:registrant)
@existing_user_hash = {
'provider' => 'rant_tara',
'uid' => "US1234",
'info': { 'first_name': 'Registrant', 'last_name': 'User' }
}
@new_user_hash = {
'provider' => 'rant_tara',
'uid' => 'EE51007050604',
'info': { 'first_name': 'New Registrant', 'last_name': 'User'}
}
end
def teardown
super
OmniAuth.config.test_mode = false
OmniAuth.config.mock_auth['rant_tara'] = nil
end
def test_existing_user_gets_signed_in
OmniAuth.config.mock_auth[:rant_tara] = OmniAuth::AuthHash.new(@existing_user_hash)
visit new_registrant_user_session_path
click_link('Sign in')
assert_text('Signed in successfully')
end
def test_new_user_is_created_and_signed_in
OmniAuth.config.mock_auth[:rant_tara] = OmniAuth::AuthHash.new(@new_user_hash)
assert_difference 'RegistrantUser.count' do
visit new_registrant_user_session_path
click_link('Sign in')
assert_equal 'New Registrant User', RegistrantUser.last.username
assert_equal 'EE-51007050604', RegistrantUser.last.registrant_ident
assert_text('Signed in successfully')
end
end
end

View file

@ -1,35 +0,0 @@
require 'application_system_test_case'
class RegistrarAreaMobileIDSignInTest < JavaScriptApplicationSystemTestCase
def setup
super
WebMock.allow_net_connect!
@user = users(:api_bestnames)
@user.identity_code = '1234'
@user.save
end
def test_valid_phone_number
mock_client = Minitest::Mock.new
mock_client.expect(:authenticate,
OpenStruct.new(user_id_code: '1234', challenge_id: '1234'),
[{ phone: "+3721234",
message_to_display: "Authenticating",
service_name: "Testimine" }])
mock_client.expect(:session_code, 1234)
Digidoc::Client.stub(:new, mock_client) do
visit new_registrar_user_session_path
click_on 'login-with-mobile-id-btn'
fill_in 'user[phone]', with: '1234'
click_button 'Login'
flash_message = page.find('div.bg-success')
assert_equal('Confirmation sms was sent to your phone. Verification code is 1234.',
flash_message.text)
end
end
end

View file

@ -0,0 +1,45 @@
require 'application_system_test_case'
class TaraUsersTest < ApplicationSystemTestCase
def setup
super
OmniAuth.config.test_mode = true
@user = users(:api_bestnames)
@existing_user_hash = {
'provider' => 'tara',
'uid' => "EE" + @user.identity_code
}
@new_user_hash = {
'provider' => 'tara',
'uid' => 'EE51007050604'
}
end
def teardown
super
OmniAuth.config.test_mode = false
OmniAuth.config.mock_auth['tara'] = nil
end
def test_existing_user_gets_signed_in
OmniAuth.config.mock_auth[:tara] = OmniAuth::AuthHash.new(@existing_user_hash)
visit new_registrar_user_session_path
click_link('Sign in')
assert_text('Signed in successfully')
end
def test_nonexisting_user_gets_error_message
OmniAuth.config.mock_auth[:tara] = OmniAuth::AuthHash.new(@new_user_hash)
visit new_registrar_user_session_path
click_link('Sign in')
assert_text('No such user')
end
end

View file

@ -27,10 +27,10 @@ Rake::Task.clear
Rails.application.load_tasks
class CompanyRegisterClientStub
Company = Struct.new(:registration_number)
Company = Struct.new(:registration_number, :company_name)
def representation_rights(citizen_personal_code:, citizen_country_code:)
[Company.new('1234567')]
[Company.new('1234567', 'ACME Ltd')]
end
end