diff --git a/.ruby-version b/.ruby-version
index e30309f73..57cf282eb 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.4.7
+2.6.5
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c0670abc8..cdc184c6e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,71 @@
+30.04.2020
+* Fix for internal error on opening domain history with legacy id record [#1576](https://github.com/internetee/registry/issues/1576)
+
+27.04.2020
+* Downgrade SimpleCov to 0.17 due to incompatibiilty with CodeClimate [#1575](https://github.com/internetee/registry/pull/1575)
+
+17.04.2020
+* Webinterfaces have now clickable version string pointing to the latest deployed commit in github [#1345](https://github.com/internetee/registry/pull/1345)
+
+15.04.2020
+* Updated Rails to 5.2 and fixed acitionview security issue [#1568](https://github.com/internetee/registry/issues/1568)
+
+25.03.2020
+* Implemented Directo gem [#1547](https://github.com/internetee/registry/pull/1547)
+
+11.03.2020
+* Fixed glue record issues when using 2nd level domain as host [#1562](https://github.com/internetee/registry/issues/1562)
+
+10.03.2020
+* Updated lhv, e-invoice & company_register gem due to security updates [#1564](https://github.com/internetee/registry/pull/1564)
+
+06.03.2020
+* Record payment method and failed payments [#1422](https://github.com/internetee/registry/issues/1422)
+
+04.03.2020
+* Bump Puma to 4.3.3 [#1557](https://github.com/internetee/registry/pull/1557)
+
+03.03.2020
+* Admin: fixed import of th6 bank statement [#1551](https://github.com/internetee/registry/issues/1551)
+
+02.03.2020
+* Registrar: fixed statuses based contact filtering [#1004](https://github.com/internetee/registry/issues/1004)
+
+28.02.2020
+* Registrar: fixed account switching [#1535](https://github.com/internetee/registry/issues/1535)
+
+27.02.2020
+* Registrar: fixed the verified checkbox bug that did not change the element value to yes in epp request [#1540](https://github.com/internetee/registry/issues/1540)
+* Ruby version update to 2.6.5 [#1545](https://github.com/internetee/registry/pull/1545)
+
+26.02.2020
+* Registrar: added an option to remove clientHold status [#1481](https://github.com/internetee/registry/issues/1481)
+* Admin: fixed domain status removal issue [#1543](https://github.com/internetee/registry/issues/1543)
+* Implemented consistent and automated data migrations [#1298](https://github.com/internetee/registry/issues/1298)
+
+20.02.2020
+* E-invoice sending to Que to manage resending in case of an error [#1509](https://github.com/internetee/registry/issues/1509)
+* Check to make sure all monthly invoices fit in available invoice number range [#277](https://github.com/internetee/registry/issues/277)
+* Disabled aurbreak performance monitoring [#1534](https://github.com/internetee/registry/pull/1534)
+
+14.02.2020
+* Fixed Papertrail warnings [#1530](https://github.com/internetee/registry/issues/1530)
+
+12.02.2020
+* Fixed papertrails double recording issue [#1526](https://github.com/internetee/registry/issues/1526)
+* Requests to Directo are now saved for both credit and monthly invoices [#344](https://github.com/internetee/registry/issues/344)
+
+10.02.2020
+* Resolved Money gem deprecation warning and silenced all warnings due plan to replace papertrail [#1522](https://github.com/internetee/registry/pull/1522)
+
+06.02.2020
+* Permit & turn ActiveController::Parameters to hash on domain create [#1516](https://github.com/internetee/registry/issues/1516)
+
+05.02.2020
+* Ruby version upgrade to 2.6.3 [#846](https://github.com/internetee/registry/issues/846)
+* Added retries & raise to connect api to handle timeouts [#1474](https://github.com/internetee/registry/issues/1474)
+* Added logging of XML if there is NoMethodError#text on xml data fields [#1475](https://github.com/internetee/registry/issues/1475)
+
04.02.2020
* Fixed bug that allowed bypassing blocked domain validation using punycode [#1142](https://github.com/internetee/registry/issues/1142)
* SimpleIDN gem update to 0.0.9 [#1508](https://github.com/internetee/registry/pull/1508)
diff --git a/Dockerfile b/Dockerfile
index 7e3b11d80..5d241eeef 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM internetee/ruby:2.4
+FROM internetee/ruby:2.6-buster
RUN mkdir -p /opt/webapps/app/tmp/pids
WORKDIR /opt/webapps/app
diff --git a/Gemfile b/Gemfile
index b3882e792..851094689 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,8 +1,8 @@
source 'https://rubygems.org'
# core
-gem 'iso8601', '0.8.6' # for dates and times
-gem 'rails', '~> 5.0.7'
+gem 'iso8601', '0.12.1' # for dates and times
+gem 'rails', '~> 5.2.4.2'
gem 'rest-client'
gem 'uglifier'
@@ -10,11 +10,11 @@ gem 'uglifier'
gem 'figaro', '1.1.1'
# model related
-gem 'pg', '0.19.0'
+gem 'paper_trail', '~> 9.2'
+gem 'pg', '1.2.2'
# 1.8 is for Rails < 5.0
-gem 'ransack', '~> 1.8'
+gem 'ransack', '~> 2.3'
gem 'validates_email_format_of', '1.6.3' # validates email against RFC 2822 and RFC 3696
-gem 'paper_trail', '~> 4.0'
# 0.7.3 is the latest for Rails 4.2, however, it is absent on Rubygems server
# https://github.com/huacnlee/rails-settings-cached/issues/165
@@ -36,10 +36,10 @@ gem 'devise', '~> 4.7'
gem 'grape'
# registry specfic
+gem 'data_migrate', '~> 6.1'
gem 'isikukood' # for EE-id validation
gem 'simpleidn', '0.0.9' # For punycode
gem 'money-rails'
-gem 'data_migrate'
gem 'whenever', '0.9.4', require: false
# country listing
@@ -63,11 +63,13 @@ gem 'airbrake'
gem 'company_register', github: 'internetee/company_register', branch: :master
gem 'e_invoice', github: 'internetee/e_invoice', branch: :master
-gem 'lhv', github: 'internetee/lhv', tag: 'v0.1.0'
+gem 'lhv', github: 'internetee/lhv', branch: :master
gem 'domain_name'
gem 'haml', '~> 5.0'
gem 'wkhtmltopdf-binary'
+gem 'directo', github: 'internetee/directo', branch: 'master'
+
group :development do
# deploy
gem 'mina', '0.3.1' # for fast deployment
@@ -84,8 +86,8 @@ end
group :test do
gem 'capybara'
gem 'database_cleaner'
- gem 'simplecov', require: false
+ gem 'minitest', '~> 5.14'
+ gem 'simplecov', '0.17.1', require: false # CC last supported v0.17
gem 'webdrivers'
gem 'webmock'
- gem 'minitest', '~> 5.10.0'
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 23aa90a51..fe737f7ac 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,15 +1,24 @@
GIT
remote: https://github.com/internetee/company_register.git
- revision: da7130542304fc543c90d54cd037d019a777c526
+ revision: 86d691997aa7def9f86d88f6c92cabb86cd65487
branch: master
specs:
company_register (0.1.0)
activesupport
savon
+GIT
+ remote: https://github.com/internetee/directo.git
+ revision: 8cb63d2fb91c640b264d5af05f4a6afbcfd46979
+ branch: master
+ specs:
+ directo (1.0.0)
+ money (~> 6.13)
+ nokogiri (~> 1.10)
+
GIT
remote: https://github.com/internetee/e_invoice.git
- revision: 3a754974ed25569aa85d99a87ae9e131b7c10a24
+ revision: b374ffd7be77b559b30c7a0210dc0df5ac3ed723
branch: master
specs:
e_invoice (0.1.0)
@@ -27,7 +36,7 @@ GIT
GIT
remote: https://github.com/internetee/epp.git
- revision: 76f9fd487d0ca3865b6f706c5a72703951c03996
+ revision: af7cefda37ac81d14b1d12641cde410776082d59
branch: master
specs:
epp (1.5.0)
@@ -36,11 +45,12 @@ GIT
GIT
remote: https://github.com/internetee/lhv.git
- revision: e211516bc5fff2139584d4da41c17511863c229d
- tag: v0.1.0
+ revision: cf0d30816ca9cd6a35d206aa1007c378f8acb502
+ branch: master
specs:
lhv (0.1.0)
keystores
+ logger
nokogiri
GIT
@@ -58,70 +68,70 @@ GIT
GEM
remote: https://rubygems.org/
specs:
- actioncable (5.0.7.2)
- actionpack (= 5.0.7.2)
- nio4r (>= 1.2, < 3.0)
- websocket-driver (~> 0.6.1)
- actionmailer (5.0.7.2)
- actionpack (= 5.0.7.2)
- actionview (= 5.0.7.2)
- activejob (= 5.0.7.2)
+ actioncable (5.2.4.2)
+ actionpack (= 5.2.4.2)
+ nio4r (~> 2.0)
+ websocket-driver (>= 0.6.1)
+ actionmailer (5.2.4.2)
+ actionpack (= 5.2.4.2)
+ actionview (= 5.2.4.2)
+ activejob (= 5.2.4.2)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (5.0.7.2)
- actionview (= 5.0.7.2)
- activesupport (= 5.0.7.2)
- rack (~> 2.0)
- rack-test (~> 0.6.3)
+ actionpack (5.2.4.2)
+ actionview (= 5.2.4.2)
+ activesupport (= 5.2.4.2)
+ rack (~> 2.0, >= 2.0.8)
+ rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (5.0.7.2)
- activesupport (= 5.0.7.2)
+ actionview (5.2.4.2)
+ activesupport (= 5.2.4.2)
builder (~> 3.1)
- erubis (~> 2.7.0)
+ erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
- activejob (5.0.7.2)
- activesupport (= 5.0.7.2)
+ activejob (5.2.4.2)
+ activesupport (= 5.2.4.2)
globalid (>= 0.3.6)
- activemodel (5.0.7.2)
- activesupport (= 5.0.7.2)
- activerecord (5.0.7.2)
- activemodel (= 5.0.7.2)
- activesupport (= 5.0.7.2)
- arel (~> 7.0)
- activesupport (5.0.7.2)
+ activemodel (5.2.4.2)
+ activesupport (= 5.2.4.2)
+ activerecord (5.2.4.2)
+ activemodel (= 5.2.4.2)
+ activesupport (= 5.2.4.2)
+ arel (>= 9.0)
+ activestorage (5.2.4.2)
+ actionpack (= 5.2.4.2)
+ activerecord (= 5.2.4.2)
+ marcel (~> 0.3.1)
+ activesupport (5.2.4.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
- airbrake (9.4.5)
- airbrake-ruby (~> 4.7)
- airbrake-ruby (4.7.1)
+ airbrake (10.0.1)
+ airbrake-ruby (~> 4.13)
+ airbrake-ruby (4.13.0)
rbtree3 (~> 0.5)
akami (1.3.1)
gyoku (>= 0.4.0)
nokogiri
- arel (7.1.4)
+ arel (9.0.0)
autodoc (0.7.3)
actionpack
activesupport (>= 3.0.0)
rspec
- autoprefixer-rails (9.6.5)
+ autoprefixer-rails (9.7.4)
execjs
- axiom-types (0.1.1)
- descendants_tracker (~> 0.0.4)
- ice_nine (~> 0.11.0)
- thread_safe (~> 0.3, >= 0.3.1)
bcrypt (3.1.13)
bootstrap-sass (3.4.1)
autoprefixer-rails (>= 5.2.1)
sassc (>= 2.0.0)
- builder (3.2.3)
- cancancan (3.0.1)
- capybara (3.29.0)
+ builder (3.2.4)
+ cancancan (3.0.2)
+ capybara (3.31.0)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
@@ -132,8 +142,6 @@ GEM
childprocess (3.0.0)
chronic (0.10.2)
coderay (1.1.0)
- coercible (1.0.0)
- descendants_tracker (~> 0.0.1)
coffee-rails (4.2.2)
coffee-script (>= 2.2.0)
railties (>= 4.0.0)
@@ -141,23 +149,21 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.12.2)
- concurrent-ruby (1.1.5)
+ concurrent-ruby (1.1.6)
countries (3.0.0)
i18n_data (~> 0.8.0)
sixarm_ruby_unaccent (~> 1.1)
unicode_utils (~> 1.4)
crack (0.4.3)
safe_yaml (~> 1.0.0)
- crass (1.0.5)
+ crass (1.0.6)
daemons (1.3.1)
daemons-rails (1.2.1)
daemons
multi_json (~> 1.0)
- data_migrate (6.0.5)
+ data_migrate (6.2.0)
rails (>= 5.0)
- database_cleaner (1.7.0)
- descendants_tracker (0.0.4)
- thread_safe (~> 0.3, >= 0.3.1)
+ database_cleaner (1.8.2)
devise (4.7.1)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
@@ -168,21 +174,42 @@ GEM
docile (1.3.2)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
- equalizer (0.0.11)
+ dry-configurable (0.9.0)
+ concurrent-ruby (~> 1.0)
+ dry-core (~> 0.4, >= 0.4.7)
+ dry-container (0.7.2)
+ concurrent-ruby (~> 1.0)
+ dry-configurable (~> 0.1, >= 0.1.3)
+ dry-core (0.4.9)
+ concurrent-ruby (~> 1.0)
+ dry-equalizer (0.3.0)
+ dry-inflector (0.2.0)
+ dry-logic (1.0.5)
+ concurrent-ruby (~> 1.0)
+ dry-core (~> 0.2)
+ dry-equalizer (~> 0.2)
+ dry-types (1.2.2)
+ concurrent-ruby (~> 1.0)
+ dry-container (~> 0.3)
+ dry-core (~> 0.4, >= 0.4.4)
+ dry-equalizer (~> 0.3)
+ dry-inflector (~> 0.1, >= 0.1.2)
+ dry-logic (~> 1.0, >= 1.0.2)
+ erubi (1.9.0)
erubis (2.7.0)
execjs (2.7.0)
- ffi (1.11.1)
+ ffi (1.12.2)
figaro (1.1.1)
thor (~> 0.14)
globalid (0.4.2)
activesupport (>= 4.2.0)
- grape (1.2.4)
+ grape (1.3.0)
activesupport
builder
+ dry-types (>= 1.1)
mustermann-grape (~> 1.0.0)
rack (>= 1.3.0)
rack-accept
- virtus (>= 1.0.0)
gyoku (1.3.1)
builder (>= 2.1.2)
haml (5.1.2)
@@ -197,12 +224,11 @@ GEM
httpi (2.4.4)
rack
socksify
- i18n (1.7.0)
+ i18n (1.8.2)
concurrent-ruby (~> 1.0)
i18n_data (0.8.0)
- ice_nine (0.11.2)
isikukood (0.1.2)
- iso8601 (0.8.6)
+ iso8601 (0.12.1)
jquery-rails (4.3.5)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
@@ -210,92 +236,101 @@ GEM
jquery-ui-rails (5.0.5)
railties (>= 3.2.16)
json (1.8.6)
- kaminari (1.1.1)
+ kaminari (1.2.0)
activesupport (>= 4.1.0)
- kaminari-actionview (= 1.1.1)
- kaminari-activerecord (= 1.1.1)
- kaminari-core (= 1.1.1)
- kaminari-actionview (1.1.1)
+ kaminari-actionview (= 1.2.0)
+ kaminari-activerecord (= 1.2.0)
+ kaminari-core (= 1.2.0)
+ kaminari-actionview (1.2.0)
actionview
- kaminari-core (= 1.1.1)
- kaminari-activerecord (1.1.1)
+ kaminari-core (= 1.2.0)
+ kaminari-activerecord (1.2.0)
activerecord
- kaminari-core (= 1.1.1)
- kaminari-core (1.1.1)
+ kaminari-core (= 1.2.0)
+ kaminari-core (1.2.0)
keystores (0.4.0)
libxml-ruby (3.1.0)
- loofah (2.3.1)
+ logger (1.4.2)
+ loofah (2.5.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
mini_mime (>= 0.1.1)
+ marcel (0.3.3)
+ mimemagic (~> 0.3.2)
method_source (0.8.2)
- mime-types (3.3)
+ mime-types (3.3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2019.1009)
+ mimemagic (0.3.4)
mina (0.3.1)
open4 (~> 1.3.4)
rake
mini_mime (1.0.2)
mini_portile2 (2.4.0)
- minitest (5.10.3)
- monetize (1.9.2)
+ minitest (5.14.0)
+ monetize (1.9.4)
money (~> 6.12)
- money (6.13.4)
+ money (6.13.7)
i18n (>= 0.6.4, <= 2)
- money-rails (1.13.2)
+ money-rails (1.13.3)
activesupport (>= 3.0)
monetize (~> 1.9.0)
money (~> 6.13.2)
railties (>= 3.0)
multi_json (1.14.1)
- mustermann (1.0.3)
- mustermann-grape (1.0.0)
- mustermann (~> 1.0.0)
+ mustermann (1.1.1)
+ ruby2_keywords (~> 0.0.1)
+ mustermann-grape (1.0.1)
+ mustermann (>= 1.0.0)
netrc (0.11.0)
nio4r (2.5.2)
- nokogiri (1.10.4)
+ nokogiri (1.10.9)
mini_portile2 (~> 2.4.0)
nori (2.6.0)
open4 (1.3.4)
orm_adapter (0.5.0)
- paper_trail (4.2.0)
- activerecord (>= 3.0, < 6.0)
- activesupport (>= 3.0, < 6.0)
+ paper_trail (9.2.0)
+ activerecord (>= 4.2, < 5.3)
+ paper_trail-association_tracking (< 2)
request_store (~> 1.1)
+ paper_trail-association_tracking (1.1.1)
pdfkit (0.8.4.1)
- pg (0.19.0)
+ pg (1.2.2)
+ polyamorous (2.3.2)
+ activerecord (>= 5.2.1)
pry (0.10.1)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
- public_suffix (4.0.1)
- puma (4.3.1)
+ public_suffix (4.0.3)
+ puma (4.3.3)
nio4r (~> 2.0)
que (0.14.3)
que-web (0.7.2)
erubis
que (~> 0.8)
sinatra
- rack (2.0.8)
+ rack (2.2.2)
rack-accept (0.4.5)
rack (>= 0.4)
- rack-protection (2.0.7)
+ rack-protection (2.0.8.1)
rack
- rack-test (0.6.3)
- rack (>= 1.0)
+ rack-test (1.1.0)
+ rack (>= 1.0, < 3)
railroady (1.3.0)
- rails (5.0.7.2)
- actioncable (= 5.0.7.2)
- actionmailer (= 5.0.7.2)
- actionpack (= 5.0.7.2)
- actionview (= 5.0.7.2)
- activejob (= 5.0.7.2)
- activemodel (= 5.0.7.2)
- activerecord (= 5.0.7.2)
- activesupport (= 5.0.7.2)
+ rails (5.2.4.2)
+ actioncable (= 5.2.4.2)
+ actionmailer (= 5.2.4.2)
+ actionpack (= 5.2.4.2)
+ actionview (= 5.2.4.2)
+ activejob (= 5.2.4.2)
+ activemodel (= 5.2.4.2)
+ activerecord (= 5.2.4.2)
+ activestorage (= 5.2.4.2)
+ activesupport (= 5.2.4.2)
bundler (>= 1.3.0)
- railties (= 5.0.7.2)
+ railties (= 5.2.4.2)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
@@ -304,25 +339,25 @@ GEM
loofah (~> 2.3)
rails-settings-cached (0.7.2)
rails (>= 4.2.0)
- railties (5.0.7.2)
- actionpack (= 5.0.7.2)
- activesupport (= 5.0.7.2)
+ railties (5.2.4.2)
+ actionpack (= 5.2.4.2)
+ activesupport (= 5.2.4.2)
method_source
rake (>= 0.8.7)
- thor (>= 0.18.1, < 2.0)
- rake (13.0.0)
- ransack (1.8.10)
- actionpack (>= 3.0, < 5.2)
- activerecord (>= 3.0, < 5.2)
- activesupport (>= 3.0, < 5.2)
+ thor (>= 0.19.0, < 2.0)
+ rake (13.0.1)
+ ransack (2.3.2)
+ activerecord (>= 5.2.1)
+ activesupport (>= 5.2.1)
i18n
+ polyamorous (= 2.3.2)
rb-fsevent (0.10.3)
- rb-inotify (0.10.0)
+ rb-inotify (0.10.1)
ffi (~> 1.0)
- rbtree3 (0.5.0)
+ rbtree3 (0.6.0)
rdoc (4.3.0)
regexp_parser (1.6.0)
- request_store (1.4.1)
+ request_store (1.5.0)
rack (>= 1.4)
responders (3.0.0)
actionpack (>= 5.0)
@@ -336,16 +371,17 @@ GEM
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
- rspec-core (3.9.0)
- rspec-support (~> 3.9.0)
+ rspec-core (3.9.1)
+ rspec-support (~> 3.9.1)
rspec-expectations (3.9.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
- rspec-mocks (3.9.0)
+ rspec-mocks (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
- rspec-support (3.9.0)
- rubyzip (2.0.0)
+ rspec-support (3.9.2)
+ ruby2_keywords (0.0.2)
+ rubyzip (2.2.0)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
@@ -374,7 +410,7 @@ GEM
select2-rails (3.5.9.3)
thor (~> 0.14)
selectize-rails (0.12.1)
- selenium-webdriver (3.142.6)
+ selenium-webdriver (3.142.7)
childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2)
simplecov (0.17.1)
@@ -383,10 +419,10 @@ GEM
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
simpleidn (0.0.9)
- sinatra (2.0.7)
+ sinatra (2.0.8.1)
mustermann (~> 1.0)
rack (~> 2.0)
- rack-protection (= 2.0.7)
+ rack-protection (= 2.0.8.1)
tilt (~> 2.0)
sixarm_ruby_unaccent (1.2.0)
slop (3.6.0)
@@ -402,7 +438,7 @@ GEM
thor (0.20.3)
thread_safe (0.3.6)
tilt (2.0.10)
- tzinfo (1.2.5)
+ tzinfo (1.2.7)
thread_safe (~> 0.1)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
@@ -412,30 +448,25 @@ GEM
unicode_utils (1.4.0)
validates_email_format_of (1.6.3)
i18n
- virtus (1.0.5)
- axiom-types (~> 0.1)
- coercible (~> 1.0)
- descendants_tracker (~> 0.0, >= 0.0.3)
- equalizer (~> 0.0, >= 0.0.9)
warden (1.2.8)
rack (>= 2.0.6)
wasabi (3.5.0)
httpi (~> 2.0)
nokogiri (>= 1.4.2)
- webdrivers (4.1.3)
+ webdrivers (4.2.0)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (>= 3.0, < 4.0)
- webmock (3.7.6)
+ webmock (3.8.0)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
- websocket-driver (0.6.5)
+ websocket-driver (0.7.1)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.4)
whenever (0.9.4)
chronic (>= 0.6.3)
- wkhtmltopdf-binary (0.12.4)
+ wkhtmltopdf-binary (0.12.5.1)
xpath (3.2.0)
nokogiri (~> 1.8)
@@ -453,10 +484,11 @@ DEPENDENCIES
company_register!
countries
daemons-rails (= 1.2.1)
- data_migrate
+ data_migrate (~> 6.1)
database_cleaner
devise (~> 4.7)
digidoc_client!
+ directo!
domain_name
e_invoice!
epp!
@@ -465,32 +497,32 @@ DEPENDENCIES
grape
haml (~> 5.0)
isikukood
- iso8601 (= 0.8.6)
+ iso8601 (= 0.12.1)
jquery-rails
jquery-ui-rails (= 5.0.5)
kaminari
lhv!
mina (= 0.3.1)
- minitest (~> 5.10.0)
+ minitest (~> 5.14)
money-rails
nokogiri
- paper_trail (~> 4.0)
+ paper_trail (~> 9.2)
pdfkit
- pg (= 0.19.0)
+ pg (= 1.2.2)
pry (= 0.10.1)
puma
que
que-web
railroady (= 1.3.0)
- rails (~> 5.0.7)
+ rails (~> 5.2.4.2)
rails-settings-cached (= 0.7.2)
- ransack (~> 1.8)
+ ransack (~> 2.3)
rest-client
sass-rails (= 5.0.6)
sdoc (= 0.4.1)
select2-rails (= 3.5.9.3)
selectize-rails (= 0.12.1)
- simplecov
+ simplecov (= 0.17.1)
simpleidn (= 0.0.9)
uglifier
validates_email_format_of (= 1.6.3)
@@ -500,4 +532,4 @@ DEPENDENCIES
wkhtmltopdf-binary
BUNDLED WITH
- 2.0.2
+ 2.1.4
diff --git a/app/assets/stylesheets/shared/general.sass b/app/assets/stylesheets/shared/general.sass
index 07b92cdbe..6d1c4956d 100644
--- a/app/assets/stylesheets/shared/general.sass
+++ b/app/assets/stylesheets/shared/general.sass
@@ -15,6 +15,9 @@ body > .container
padding-top: 15px
font-size: 10px
+a.footer-version-link
+ color: black
+
.nowrap
white-space: nowrap
diff --git a/app/controllers/admin/bank_statements_controller.rb b/app/controllers/admin/bank_statements_controller.rb
index a70387317..1e3b31bf5 100644
--- a/app/controllers/admin/bank_statements_controller.rb
+++ b/app/controllers/admin/bank_statements_controller.rb
@@ -60,7 +60,7 @@ module Admin
end
def bind_invoices
- @bank_statement.bind_invoices
+ @bank_statement.bind_invoices(manual: true)
flash[:notice] = t('invoices_were_fully_binded') if @bank_statement.fully_binded?
flash[:warning] = t('invoices_were_partially_binded') if @bank_statement.partially_binded?
diff --git a/app/controllers/admin/bank_transactions_controller.rb b/app/controllers/admin/bank_transactions_controller.rb
index 1ce62b279..348cadc64 100644
--- a/app/controllers/admin/bank_transactions_controller.rb
+++ b/app/controllers/admin/bank_transactions_controller.rb
@@ -34,7 +34,7 @@ module Admin
end
def bind
- if @bank_transaction.bind_invoice(params[:invoice_no])
+ if @bank_transaction.bind_invoice(params[:invoice_no], manual: true)
flash[:notice] = I18n.t('record_created')
redirect_to [:admin, @bank_transaction]
else
diff --git a/app/controllers/admin/zonefiles_controller.rb b/app/controllers/admin/zonefiles_controller.rb
index 30b4b9a61..4fd84bb77 100644
--- a/app/controllers/admin/zonefiles_controller.rb
+++ b/app/controllers/admin/zonefiles_controller.rb
@@ -13,7 +13,7 @@ module Admin
send_data @zonefile, filename: "#{params[:origin]}.txt"
else
flash[:alert] = 'Origin not supported'
- redirect_to :back
+ redirect_back(fallback_location: root_path)
end
end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 1a57b5573..5a6b45668 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,5 +1,6 @@
class ApplicationController < ActionController::Base
check_authorization unless: :devise_controller?
+ before_action :set_paper_trail_whodunnit
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
@@ -32,4 +33,4 @@ class ApplicationController < ActionController::Base
def available_languages
{ en: 'English', et: 'Estonian' }.invert
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/epp/base_controller.rb b/app/controllers/epp/base_controller.rb
index 6e3f39e46..fb48c285a 100644
--- a/app/controllers/epp/base_controller.rb
+++ b/app/controllers/epp/base_controller.rb
@@ -10,7 +10,7 @@ module Epp
before_action :latin_only
before_action :validate_against_schema
before_action :validate_request
- before_action :update_epp_session, if: 'signed_in?'
+ before_action :update_epp_session, if: -> { signed_in? }
around_action :wrap_exceptions
diff --git a/app/controllers/epp/domains_controller.rb b/app/controllers/epp/domains_controller.rb
index 1295f558e..9e4f6123a 100644
--- a/app/controllers/epp/domains_controller.rb
+++ b/app/controllers/epp/domains_controller.rb
@@ -2,6 +2,7 @@ module Epp
class DomainsController < BaseController
before_action :find_domain, only: %i[info renew update transfer delete]
before_action :find_password, only: %i[info update transfer delete]
+ before_action :set_paper_trail_whodunnit
def info
authorize! :info, @domain
diff --git a/app/controllers/epp/sessions_controller.rb b/app/controllers/epp/sessions_controller.rb
index 2175f7281..ef8f125ee 100644
--- a/app/controllers/epp/sessions_controller.rb
+++ b/app/controllers/epp/sessions_controller.rb
@@ -1,6 +1,7 @@
module Epp
class SessionsController < BaseController
skip_authorization_check only: [:hello, :login, :logout]
+ before_action :set_paper_trail_whodunnit
def hello
render_epp_response('greeting')
diff --git a/app/controllers/registrar/contacts_controller.rb b/app/controllers/registrar/contacts_controller.rb
index bd1e29a7c..18af3a29f 100644
--- a/app/controllers/registrar/contacts_controller.rb
+++ b/app/controllers/registrar/contacts_controller.rb
@@ -17,12 +17,13 @@ class Registrar
search_params[:registrant_domains_id_not_null] = 1
end
- if params[:statuses_contains]
- contacts = current_registrar_user.registrar.contacts.includes(:registrar).where(
- "contacts.statuses @> ?::varchar[]", "{#{params[:statuses_contains].join(',')}}"
- )
- else
- contacts = current_registrar_user.registrar.contacts.includes(:registrar)
+ contacts = current_registrar_user.registrar.contacts.includes(:registrar)
+ status_list = params[:statuses_contains]
+
+ if status_list
+ contacts_ids = contacts.select { |c| (c.statuses & status_list.to_a) == status_list.to_a }
+ .map(&:id)
+ contacts = contacts.where(id: contacts_ids)
end
normalize_search_parameters do
diff --git a/app/controllers/registrar/current_user_controller.rb b/app/controllers/registrar/current_user_controller.rb
index 624ee294e..3a214322c 100644
--- a/app/controllers/registrar/current_user_controller.rb
+++ b/app/controllers/registrar/current_user_controller.rb
@@ -6,7 +6,7 @@ class Registrar
raise 'Cannot switch to unlinked user' unless current_registrar_user.linked_with?(new_user)
sign_in(:registrar_user, new_user)
- redirect_to :back, notice: t('.switched', new_user: new_user)
+ redirect_back(fallback_location: root_path, notice: t('.switched', new_user: new_user))
end
private
diff --git a/app/controllers/registrar/domains_controller.rb b/app/controllers/registrar/domains_controller.rb
index f533a874c..e6e1029f6 100644
--- a/app/controllers/registrar/domains_controller.rb
+++ b/app/controllers/registrar/domains_controller.rb
@@ -59,6 +59,7 @@ class Registrar
def info
authorize! :info, Depp::Domain
@data = @domain.info(params[:domain_name]) if params[:domain_name]
+ @client_holded = client_holded(@data)
if response_ok?
render 'info'
else
@@ -85,7 +86,7 @@ class Registrar
def create
authorize! :create, Depp::Domain
- @domain_params = params[:domain]
+ @domain_params = domain_params.to_h
@data = @domain.create(@domain_params)
if response_ok?
@@ -153,12 +154,26 @@ class Registrar
render json: scope.pluck(:name, :code).map { |c| { display_key: "#{c.second} #{c.first}", value: c.second } }
end
+ def remove_hold
+ authorize! :remove_hold, Depp::Domain
+ return unless params[:domain_name]
+
+ @data = @domain.remove_hold(params)
+
+ flash[:alert] = @data.css('msg').text unless response_ok?
+ redirect_to info_registrar_domains_url(domain_name: params[:domain_name])
+ end
+
private
def init_domain
@domain = Depp::Domain.new(current_user: depp_current_user)
end
+ def client_holded(data)
+ data.css('status')&.map { |element| element.attribute('s').value }
+ &.any? { |status| status == DomainStatus::CLIENT_HOLD }
+ end
def contacts
current_registrar_user.registrar.contacts
@@ -187,5 +202,12 @@ class Registrar
:valid_to_lteq,
:s)
end
+
+ def domain_params
+ params.require(:domain).permit(:name, :period, :registrant, :registrant_helper, :reserved_pw,
+ :verified, :legal_document, contacts_attributes: {},
+ nameservers_attributes: {},
+ dnskeys_attributes: {})
+ end
end
end
diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb
index 8df9bb046..598d13446 100644
--- a/app/controllers/registrar/payments_controller.rb
+++ b/app/controllers/registrar/payments_controller.rb
@@ -5,50 +5,51 @@ class Registrar
skip_authorization_check # actually anyone can pay, no problems at all
skip_before_action :authenticate_registrar_user!, :check_ip_restriction,
only: [:back, :callback]
- before_action :check_supported_payment_method
+
+ before_action :check_supported_payment_method, only: [:pay]
def pay
invoice = Invoice.find(params[:invoice_id])
- bank = params[:bank]
- opts = {
- return_url: registrar_return_payment_with_url(
- bank, invoice_id: invoice
- ),
- response_url: registrar_response_payment_with_url(
- bank, invoice_id: invoice
- )
- }
- @payment = ::PaymentOrders.create_with_type(bank, invoice, opts)
- @payment.create_transaction
+ channel = params[:bank]
+
+ @payment_order = PaymentOrder.new_with_type(type: channel, invoice: invoice)
+ @payment_order.save
+ @payment_order.reload
+
+ @payment_order.return_url = registrar_return_payment_with_url(@payment_order)
+ @payment_order.response_url = registrar_response_payment_with_url(@payment_order)
+
+ @payment_order.save
+ @payment_order.reload
end
def back
- invoice = Invoice.find(params[:invoice_id])
- opts = { response: params }
- @payment = ::PaymentOrders.create_with_type(params[:bank], invoice, opts)
- if @payment.valid_response_from_intermediary? && @payment.settled_payment?
- Rails.logger.info("User paid invoice ##{invoice.number} successfully")
+ @payment_order = PaymentOrder.find_by!(id: params[:payment_order])
+ @payment_order.update!(response: params.to_unsafe_h)
- @payment.complete_transaction
+ if @payment_order.payment_received?
+ @payment_order.complete_transaction
- if invoice.paid?
- flash[:notice] = t(:pending_applied)
+ if @payment_order.invoice.paid?
+ flash[:notice] = t('.payment_successful')
else
- flash[:alert] = t(:something_wrong)
+ flash[:alert] = t('.successful_payment_backend_error')
end
else
- flash[:alert] = t(:something_wrong)
+ @payment_order.create_failure_report
+ flash[:alert] = t('.payment_not_received')
end
- redirect_to registrar_invoice_path(invoice)
+ redirect_to registrar_invoice_path(@payment_order.invoice)
end
def callback
- invoice = Invoice.find(params[:invoice_id])
- opts = { response: params }
- @payment = ::PaymentOrders.create_with_type(params[:bank], invoice, opts)
+ @payment_order = PaymentOrder.find_by!(id: params[:payment_order])
+ @payment_order.update!(response: params.to_unsafe_h)
- if @payment.valid_response_from_intermediary? && @payment.settled_payment?
- @payment.complete_transaction
+ if @payment_order.payment_received?
+ @payment_order.complete_transaction
+ else
+ @payment_order.create_failure_report
end
render status: 200, json: { status: 'ok' }
@@ -57,13 +58,9 @@ class Registrar
private
def check_supported_payment_method
- return if supported_payment_method?
- raise StandardError.new("Not supported payment method")
- end
+ return if PaymentOrder.supported_method?(params[:bank], shortname: true)
-
- def supported_payment_method?
- PaymentOrders::PAYMENT_METHODS.include?(params[:bank])
+ raise(StandardError, 'Not supported payment method')
end
end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index a4a8e4912..8de3fdc70 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -33,6 +33,18 @@ module ApplicationHelper
end
end
+ def current_commit_link
+ hash = `git rev-parse --short HEAD`
+ current_repo = `git remote get-url origin`.gsub('com:', 'com/')
+ .gsub('git@', 'https://')
+ .gsub('.git', '')
+
+ link_to hash.to_s, "#{current_repo}/commit/#{hash}",
+ class: 'footer-version-link',
+ target: '_blank',
+ rel: 'noopener'
+ end
+
def creator_link(model)
return 'not present' if model.blank?
return 'unknown' if model.creator.blank?
@@ -96,4 +108,4 @@ module ApplicationHelper
def body_css_class
[controller_path.split('/').map!(&:dasherize), action_name.dasherize, 'page'].join('-')
end
-end
\ No newline at end of file
+end
diff --git a/app/jobs/directo_invoice_forward_job.rb b/app/jobs/directo_invoice_forward_job.rb
new file mode 100644
index 000000000..6c3eb034c
--- /dev/null
+++ b/app/jobs/directo_invoice_forward_job.rb
@@ -0,0 +1,125 @@
+class DirectoInvoiceForwardJob < Que::Job
+ def run(monthly: false, dry: false)
+ @dry = dry
+ (@month = Time.zone.now - 1.month) if monthly
+ api_url = ENV['directo_invoice_url']
+ sales_agent = Setting.directo_sales_agent
+ payment_term = Setting.directo_receipt_payment_term
+ @prepayment_product_id = Setting.directo_receipt_product_name
+
+ @client = DirectoApi::Client.new(api_url, sales_agent, payment_term)
+ monthly ? send_monthly_invoices : send_receipts
+ end
+
+ def send_receipts
+ unsent_invoices = Invoice.where(in_directo: false).non_cancelled
+
+ Rails.logger.info("[DIRECTO] Trying to send #{unsent_invoices.count} prepayment invoices")
+ unsent_invoices.each do |invoice|
+ unless valid_invoice_conditions?(invoice)
+ Rails.logger.info "[DIRECTO] Invoice #{invoice.number} has been skipped"
+ next
+ end
+ @client.invoices.add_with_schema(invoice: invoice.as_directo_json, schema: 'prepayment')
+ end
+
+ sync_with_directo
+ end
+
+ def send_monthly_invoices
+ Registrar.where.not(test_registrar: true).find_each do |registrar|
+ fetch_monthly_summary(registrar: registrar)
+ end
+
+ return unless @client.invoices.count.positive?
+
+ sync_with_directo
+ end
+
+ def fetch_monthly_summary(registrar:)
+ return unless registrar.cash_account
+
+ summary = registrar.monthly_summary(month: @month)
+ @client.invoices.add_with_schema(invoice: summary, schema: 'summary') unless summary.nil?
+ end
+
+ def assign_monthly_numbers
+ if directo_counter_exceedable?(@client.invoices.count)
+ raise 'Directo Counter is going to be out of period!'
+ end
+
+ min_directo = Setting.directo_monthly_number_min.presence.try(:to_i)
+ directo_number = [Setting.directo_monthly_number_last.presence.try(:to_i),
+ min_directo].compact.max || 0
+
+ @client.invoices.each do |inv|
+ directo_number += 1
+ inv.number = directo_number
+ end
+ end
+
+ def valid_invoice_conditions?(invoice)
+ if invoice.account_activity.nil? || invoice.account_activity.bank_transaction.nil? ||
+ invoice.account_activity.bank_transaction.sum.nil? ||
+ invoice.account_activity.bank_transaction.sum != invoice.total
+ return false
+
+ end
+
+ true
+ end
+
+ def sync_with_directo
+ assign_monthly_numbers if @month
+ Rails.logger.info("[Directo] - attempting to send following XML:\n #{@client.invoices.as_xml}")
+ return if @dry
+
+ res = @client.invoices.deliver(ssl_verify: false)
+ process_directo_response(res.body, @client.invoices.as_xml)
+ rescue SocketError, Errno::ECONNREFUSED, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET,
+ EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError
+ Rails.logger.info('[Directo] Failed to communicate via API')
+ end
+
+ def process_directo_response(xml, req)
+ Rails.logger.info "[Directo] - Responded with body: #{xml}"
+ Nokogiri::XML(xml).css('Result').each do |res|
+ if @month
+ mark_invoice_as_sent(res: res, req: req)
+ else
+ inv = Invoice.find_by(number: res.attributes['docid'].value.to_i)
+ mark_invoice_as_sent(invoice: inv, res: res, req: req)
+ end
+ end
+ end
+
+ def mark_invoice_as_sent(invoice: nil, res:, req:)
+ directo_record = Directo.new(response: res.as_json.to_h,
+ request: req, invoice_number: res.attributes['docid'].value.to_i)
+ if invoice
+ directo_record.item = invoice
+ invoice.update(in_directo: true)
+ else
+ update_directo_number(num: directo_record.invoice_number)
+ end
+
+ directo_record.save!
+ end
+
+ def update_directo_number(num:)
+ return unless num.to_i > Setting.directo_monthly_number_last.to_i
+
+ Setting.directo_monthly_number_last = num.to_i
+ end
+
+ def directo_counter_exceedable?(invoice_count)
+ min_directo = Setting.directo_monthly_number_min.presence.try(:to_i)
+ max_directo = Setting.directo_monthly_number_max.presence.try(:to_i)
+ last_directo = [Setting.directo_monthly_number_last.presence.try(:to_i),
+ min_directo].compact.max || 0
+
+ return true if max_directo && max_directo < (last_directo + invoice_count)
+
+ false
+ end
+end
diff --git a/app/jobs/send_e_invoice_job.rb b/app/jobs/send_e_invoice_job.rb
new file mode 100644
index 000000000..e281db14d
--- /dev/null
+++ b/app/jobs/send_e_invoice_job.rb
@@ -0,0 +1,43 @@
+class SendEInvoiceJob < Que::Job
+ def run(invoice_id)
+ invoice = run_condition(Invoice.find_by(id: invoice_id))
+
+ invoice.to_e_invoice.deliver
+ ActiveRecord::Base.transaction do
+ invoice.update(e_invoice_sent_at: Time.zone.now)
+ log_success(invoice)
+ destroy
+ end
+ rescue StandardError => e
+ log_error(invoice: invoice, error: e)
+ raise e
+ end
+
+ private
+
+ def run_condition(invoice)
+ destroy unless invoice
+ destroy if invoice.do_not_send_e_invoice?
+ invoice
+ end
+
+ def log_success(invoice)
+ id = invoice.try(:id) || invoice
+ message = "E-Invoice for an invoice with ID # #{id} was sent successfully"
+ logger.info message
+ end
+
+ def log_error(invoice:, error:)
+ id = invoice.try(:id) || invoice
+ message = <<~TEXT.squish
+ There was an error sending e-invoice for invoice with ID # #{id}.
+ The error message was the following: #{error}
+ This job will retry.
+ TEXT
+ logger.error message
+ end
+
+ def logger
+ Rails.logger
+ end
+end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 9a0676ac8..a727254ad 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -50,6 +50,7 @@ class Ability
can(:check, Epp::Domain)
can(:create, Epp::Domain)
can(:renew, Epp::Domain) { |d| d.registrar_id == @user.registrar_id }
+ can(:remove_hold, Epp::Domain) { |d| d.registrar_id == @user.registrar_id }
can(:update, Epp::Domain) { |d, pw| d.registrar_id == @user.registrar_id || d.transfer_code == pw }
can(:transfer, Epp::Domain)
can(:delete, Epp::Domain) { |d, pw| d.registrar_id == @user.registrar_id || d.transfer_code == pw }
diff --git a/app/models/admin_user.rb b/app/models/admin_user.rb
index 07686e921..159578ab0 100644
--- a/app/models/admin_user.rb
+++ b/app/models/admin_user.rb
@@ -4,7 +4,7 @@ class AdminUser < User
validates :identity_code, presence: true, if: -> { country_code == 'EE' }
validates :email, presence: true
validates :password, :password_confirmation, presence: true, if: :new_record?
- validates :password_confirmation, presence: true, if: :encrypted_password_changed?
+ validates :password_confirmation, presence: true, if: :will_save_change_to_encrypted_password?
validate :validate_identity_code, if: -> { country_code == 'EE' }
ROLES = %w(user customer_service admin) # should not match to api_users roles
diff --git a/app/models/api_user.rb b/app/models/api_user.rb
index e11dbf90f..3dc240727 100644
--- a/app/models/api_user.rb
+++ b/app/models/api_user.rb
@@ -43,7 +43,7 @@ class ApiUser < User
after_initialize :set_defaults
def set_defaults
return unless new_record?
- self.active = true unless active_changed?
+ self.active = true unless saved_change_to_active?
end
class << self
diff --git a/app/models/bank_statement.rb b/app/models/bank_statement.rb
index 8d4608f64..c73e6bb44 100644
--- a/app/models/bank_statement.rb
+++ b/app/models/bank_statement.rb
@@ -25,10 +25,16 @@ class BankStatement < ApplicationRecord
bank_transactions.build(bt_params)
end
+ prepare_dir
self.import_file_path = "#{ENV['bank_statement_import_dir']}/#{Time.zone.now.to_formatted_s(:number)}.txt"
File.open(import_file_path, 'w') { |f| f.write(th6_file.open.read) }
end
+ def prepare_dir
+ dirname = ENV['bank_statement_import_dir']
+ FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
+ end
+
def parse_th6_row(row)
return parse_th6_header(row) if row[4, 3].strip == '000'
return if row[4, 3].strip == '999' # skip footer
@@ -45,7 +51,7 @@ class BankStatement < ApplicationRecord
buyer_name: row[83, 35].strip,
document_no: row[118, 8].strip,
description: row[126, 140].strip,
- sum: BigDecimal.new(row[268, 12].strip) / BigDecimal.new('100.0'),
+ sum: BigDecimal(row[268, 12].strip) / BigDecimal('100.0'),
reference_no: row[280, 35].strip
}
end
@@ -80,7 +86,9 @@ class BankStatement < ApplicationRecord
status == FULLY_BINDED
end
- def bind_invoices
- bank_transactions.unbinded.each(&:autobind_invoice)
+ def bind_invoices(manual: false)
+ bank_transactions.unbinded.each do |transaction|
+ transaction.autobind_invoice(manual: manual)
+ end
end
end
diff --git a/app/models/bank_transaction.rb b/app/models/bank_transaction.rb
index cb9aebc5e..f53a286ba 100644
--- a/app/models/bank_transaction.rb
+++ b/app/models/bank_transaction.rb
@@ -13,6 +13,7 @@ class BankTransaction < ApplicationRecord
def binded_invoice
return unless binded?
+
account_activity.invoice
end
@@ -30,31 +31,54 @@ class BankTransaction < ApplicationRecord
@registrar ||= Invoice.find_by(reference_no: parsed_ref_number)&.buyer
end
-
# For successful binding, reference number, invoice id and sum must match with the invoice
- def autobind_invoice
+ def autobind_invoice(manual: false)
return if binded?
return unless registrar
return unless invoice
return unless invoice.payable?
- create_activity(registrar, invoice)
+ channel = if manual
+ 'admin_payment'
+ else
+ 'system_payment'
+ end
+ create_internal_payment_record(channel: channel, invoice: invoice,
+ registrar: registrar)
end
- def bind_invoice(invoice_no)
+ def create_internal_payment_record(channel: nil, invoice:, registrar:)
+ if channel.nil?
+ create_activity(invoice.buyer, invoice)
+ return
+ end
+
+ payment_order = PaymentOrder.new_with_type(type: channel, invoice: invoice)
+ payment_order.save!
+
+ if create_activity(registrar, invoice)
+ payment_order.paid!
+ else
+ payment_order.update(notes: 'Failed to create activity', status: 'failed')
+ end
+ end
+
+ def bind_invoice(invoice_no, manual: false)
if binded?
errors.add(:base, I18n.t('transaction_is_already_binded'))
return
end
invoice = Invoice.find_by(number: invoice_no)
- @registrar = invoice.buyer
+ errors.add(:base, I18n.t('invoice_was_not_found')) unless invoice
+ validate_invoice_data(invoice)
+ return if errors.any?
- unless invoice
- errors.add(:base, I18n.t('invoice_was_not_found'))
- return
- end
+ create_internal_payment_record(channel: (manual ? 'admin_payment' : nil), invoice: invoice,
+ registrar: invoice.buyer)
+ end
+ def validate_invoice_data(invoice)
if invoice.paid?
errors.add(:base, I18n.t('invoice_is_already_binded'))
return
@@ -65,23 +89,21 @@ class BankTransaction < ApplicationRecord
return
end
- if invoice.total != sum
- errors.add(:base, I18n.t('invoice_and_transaction_sums_do_not_match'))
- return
- end
-
- create_activity(invoice.buyer, invoice)
+ errors.add(:base, I18n.t('invoice_and_transaction_sums_do_not_match')) if invoice.total != sum
end
def create_activity(registrar, invoice)
- ActiveRecord::Base.transaction do
- create_account_activity!(account: registrar.cash_account,
- invoice: invoice,
- sum: invoice.subtotal,
- currency: currency,
- description: description,
- activity_type: AccountActivity::ADD_CREDIT)
+ activity = AccountActivity.new(
+ account: registrar.cash_account, bank_transaction: self,
+ invoice: invoice, sum: invoice.subtotal,
+ currency: currency, description: description,
+ activity_type: AccountActivity::ADD_CREDIT
+ )
+ if activity.save
reset_pending_registrar_balance_reload
+ true
+ else
+ false
end
end
diff --git a/app/models/concerns/contact/transferable.rb b/app/models/concerns/contact/transferable.rb
index 3f151251a..987933a8d 100644
--- a/app/models/concerns/contact/transferable.rb
+++ b/app/models/concerns/contact/transferable.rb
@@ -3,7 +3,7 @@ module Concerns::Contact::Transferable
included do
validates :auth_info, presence: true
- after_initialize :generate_auth_info, if: 'new_record? && auth_info.blank?'
+ after_initialize :generate_auth_info, if: -> { new_record? && auth_info.blank? }
end
def transfer(new_registrar)
diff --git a/app/models/concerns/invoice/book_keeping.rb b/app/models/concerns/invoice/book_keeping.rb
new file mode 100644
index 000000000..2469f45eb
--- /dev/null
+++ b/app/models/concerns/invoice/book_keeping.rb
@@ -0,0 +1,26 @@
+module Concerns
+ module Invoice
+ module BookKeeping
+ extend ActiveSupport::Concern
+
+ def as_directo_json
+ invoice = ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(self))
+ invoice['customer_code'] = buyer.accounting_customer_code
+ invoice['issue_date'] = issue_date.strftime('%Y-%m-%d')
+ invoice['transaction_date'] = account_activity
+ .bank_transaction&.paid_at&.strftime('%Y-%m-%d')
+ invoice['language'] = buyer.language == 'en' ? 'ENG' : ''
+ invoice['invoice_lines'] = compose_directo_product
+
+ invoice
+ end
+
+ def compose_directo_product
+ [{ 'product_id': Setting.directo_receipt_product_name, 'description': order,
+ 'quantity': 1, 'price': ActionController::Base.helpers.number_with_precision(
+ subtotal, precision: 2, separator: '.'
+ ) }].as_json
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/registrar/book_keeping.rb b/app/models/concerns/registrar/book_keeping.rb
new file mode 100644
index 000000000..27645d2cb
--- /dev/null
+++ b/app/models/concerns/registrar/book_keeping.rb
@@ -0,0 +1,120 @@
+module Concerns
+ module Registrar
+ module BookKeeping
+ extend ActiveSupport::Concern
+
+ DOMAIN_TO_PRODUCT = { 'ee': '01EE', 'com.ee': '02COM', 'pri.ee': '03PRI',
+ 'fie.ee': '04FIE', 'med.ee': '05MED' }.freeze
+
+ def monthly_summary(month:)
+ activities = monthly_activites(month)
+ return unless activities.any?
+
+ invoice = {
+ 'number': 1,
+ 'customer_code': accounting_customer_code,
+ 'language': language == 'en' ? 'ENG' : '', 'currency': activities.first.currency,
+ 'date': month.end_of_month.strftime('%Y-%m-%d')
+ }.as_json
+
+ invoice['invoice_lines'] = prepare_invoice_lines(month: month, activities: activities)
+
+ invoice
+ end
+
+ def prepare_invoice_lines(month:, activities:)
+ lines = []
+
+ lines << { 'description': title_for_summary(month) }
+ activities.each do |activity|
+ fetch_invoice_lines(activity, lines)
+ end
+ lines << prepayment_for_all(lines)
+
+ lines.as_json
+ end
+
+ def title_for_summary(date)
+ I18n.with_locale(language == 'en' ? 'en' : 'et') do
+ I18n.t('registrar.monthly_summary_title', date: I18n.l(date, format: '%B %Y'))
+ end
+ end
+
+ def fetch_invoice_lines(activity, lines)
+ price = load_price(activity)
+ if price.duration.include? 'year'
+ price.duration.to_i.times do |duration|
+ lines << new_monthly_invoice_line(activity: activity, duration: duration + 1).as_json
+ end
+ else
+ lines << new_monthly_invoice_line(activity: activity).as_json
+ end
+ end
+
+ def monthly_activites(month)
+ AccountActivity.where(account_id: account_ids)
+ .where(created_at: month.beginning_of_month..month.end_of_month)
+ .where(activity_type: [AccountActivity::CREATE, AccountActivity::RENEW])
+ end
+
+ def new_monthly_invoice_line(activity:, duration: nil)
+ price = load_price(activity)
+ line = {
+ 'product_id': DOMAIN_TO_PRODUCT[price.zone_name.to_sym],
+ 'quantity': 1,
+ 'unit': language == 'en' ? 'pc' : 'tk',
+ }
+
+ finalize_invoice_line(line, price: price, duration: duration, activity: activity)
+ end
+
+ def finalize_invoice_line(line, price:, activity:, duration:)
+ yearly = price.duration.include?('year')
+
+ line['price'] = yearly ? (price.price.amount / price.duration.to_i) : price.price.amount
+ line['description'] = description_in_language(price: price, yearly: yearly)
+
+ if duration.present?
+ add_product_timeframe(line: line, activity: activity, duration: duration) if duration > 1
+ end
+
+ line
+ end
+
+ def add_product_timeframe(line:, activity:, duration:)
+ create_time = activity.created_at
+ line['start_date'] = (create_time + (duration - 1).year).end_of_month.strftime('%Y-%m-%d')
+ line['end_date'] = (create_time + (duration - 1).year + 1).end_of_month.strftime('%Y-%m-%d')
+ end
+
+ def description_in_language(price:, yearly:)
+ timeframe_string = yearly ? 'yearly' : 'monthly'
+ locale_string = "registrar.invoice_#{timeframe_string}_product_description"
+
+ I18n.with_locale(language == 'en' ? 'en' : 'et') do
+ I18n.t(locale_string, tld: ".#{price.zone_name}", length: price.duration.to_i)
+ end
+ end
+
+ def prepayment_for_all(lines)
+ total = 0
+ en = language == 'en'
+ lines.each { |l| total += l['quantity'].to_f * l['price'].to_f }
+ {
+ 'product_id': Setting.directo_receipt_product_name,
+ 'description': en ? 'Domains prepayment' : 'Domeenide ettemaks',
+ 'quantity': -1,
+ 'price': total,
+ 'unit': en ? 'pc' : 'tk',
+ }
+ end
+
+ def load_price(account_activity)
+ @pricelists ||= {}
+ return @pricelists[account_activity.price_id] if @pricelists.key? account_activity.price_id
+
+ @pricelists[account_activity.price_id] = account_activity.price
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/remove_hold.rb b/app/models/concerns/remove_hold.rb
new file mode 100644
index 000000000..1da3b5a7f
--- /dev/null
+++ b/app/models/concerns/remove_hold.rb
@@ -0,0 +1,9 @@
+module RemoveHold
+ extend ActiveSupport::Concern
+
+ def remove_hold(params)
+ xml = epp_xml.update(name: { value: params[:domain_name] },
+ rem: [status: { attrs: { s: 'clientHold' }, value: '' }])
+ current_user.request(xml)
+ end
+end
diff --git a/app/models/concerns/versions.rb b/app/models/concerns/versions.rb
index b0a82376f..01766b233 100644
--- a/app/models/concerns/versions.rb
+++ b/app/models/concerns/versions.rb
@@ -1,10 +1,16 @@
# Papertrail concerns is mainly tested at country spec
module Versions
extend ActiveSupport::Concern
+ WITH_CHILDREN = %w[Domain Contact].freeze
included do
attr_accessor :version_loader
- has_paper_trail class_name: "#{model_name}Version"
+
+ if WITH_CHILDREN.include?(model_name.name)
+ has_paper_trail class_name: "#{model_name}Version", meta: { children: :children_log }
+ else
+ has_paper_trail class_name: "#{model_name}Version"
+ end
# add creator and updator
before_create :add_creator
@@ -45,17 +51,17 @@ module Versions
# callbacks
def touch_domain_version
- domain.try(:touch_with_version)
+ domain.paper_trail.try(:touch_with_version)
end
def touch_domains_version
- domains.each(&:touch_with_version)
+ domains.each { |domain| domain.paper_trail.touch_with_version }
end
end
module ClassMethods
def all_versions_for(ids, time)
- ver_klass = paper_trail_version_class
+ ver_klass = paper_trail.version_class
from_history = ver_klass.where(item_id: ids.to_a).
order(:item_id).
preceding(time + 1, true).
@@ -64,7 +70,8 @@ module Versions
valid_columns = ver.item_type.constantize&.column_names
o = new(ver.object&.slice(*valid_columns))
o.version_loader = ver
- ver.object_changes.to_h.each { |k, v| o.public_send("#{k}=", v[-1]) }
+ changes = ver.object_changes.to_h&.slice(*valid_columns)
+ changes.each { |k, v| o.public_send("#{k}=", v[-1]) }
o
end
not_in_history = where(id: (ids.to_a - from_history.map(&:id)))
diff --git a/app/models/contact.rb b/app/models/contact.rb
index ddf39c9bb..ac6facbe8 100644
--- a/app/models/contact.rb
+++ b/app/models/contact.rb
@@ -14,8 +14,6 @@ class Contact < ApplicationRecord
has_many :registrant_domains, class_name: 'Domain', foreign_key: 'registrant_id'
has_many :actions, dependent: :destroy
- has_paper_trail class_name: "ContactVersion", meta: { children: :children_log }
-
attr_accessor :legal_document_id
alias_attribute :kind, :ident_type
alias_attribute :copy_from_id, :original_id # Old attribute name; for PaperTrail
@@ -23,12 +21,14 @@ class Contact < ApplicationRecord
accepts_nested_attributes_for :legal_documents
validates :name, :email, presence: true
- validates :street, :city, :zip, :country_code, presence: true, if: 'self.class.address_processing?'
+ validates :street, :city, :zip, :country_code, presence: true, if: lambda {
+ self.class.address_processing?
+ }
validates :phone, presence: true, e164: true, phone: true
validates :email, format: /@/
- validates :email, email_format: { message: :invalid }, if: proc { |c| c.email_changed? }
+ validates :email, email_format: { message: :invalid }, if: proc { |c| c.will_save_change_to_email? }
validates :code,
uniqueness: { message: :epp_id_taken },
@@ -37,7 +37,7 @@ class Contact < ApplicationRecord
validates_associated :identifier
validate :validate_html
- validate :validate_country_code, if: 'self.class.address_processing?'
+ validate :validate_country_code, if: -> { self.class.address_processing? }
after_initialize do
self.status_notes = {} if status_notes.nil?
diff --git a/app/models/counter.rb b/app/models/counter.rb
deleted file mode 100644
index 7d1c2b926..000000000
--- a/app/models/counter.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-class Counter
- def initialize value = 0
- @value = value
- end
- attr_accessor :value
- def method_missing *args, &blk
- @value.send(*args, &blk)
- end
- def to_s
- @value.to_s
- end
-
- def now
- @value
- end
-
- # pre-increment ".+" when x not present
- def next(x = 1)
- @value += x
- end
- def prev(x = 1)
- @value -= x
- end
-end
\ No newline at end of file
diff --git a/app/models/depp/domain.rb b/app/models/depp/domain.rb
index e2413a004..3bb3b7473 100644
--- a/app/models/depp/domain.rb
+++ b/app/models/depp/domain.rb
@@ -1,6 +1,7 @@
module Depp
class Domain
include ActiveModel::Conversion
+ include RemoveHold
extend ActiveModel::Naming
attr_accessor :name, :current_user, :epp_xml
diff --git a/app/models/directo.rb b/app/models/directo.rb
index 789db64b2..a4af6c134 100644
--- a/app/models/directo.rb
+++ b/app/models/directo.rb
@@ -1,198 +1,3 @@
class Directo < ApplicationRecord
- DOMAIN_TO_PRODUCT = {"ee" => "01EE", "com.ee" => "02COM", "pri.ee" => "03PRI", "fie.ee"=>"04FIE", "med.ee" => "05MED"}.freeze
belongs_to :item, polymorphic: true
-
- def self.send_receipts
- new_trans = Invoice.where(in_directo: false).non_cancelled
- total = new_trans.count
- counter = 0
- Rails.logger.info("[DIRECTO] Will try to send #{total} invoices")
-
- new_trans.find_in_batches(batch_size: 10).each do |group|
- mappers = {} # need them as no direct connection between invoice
- builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
- xml.invoices {
- group.each do |invoice|
-
- if invoice.account_activity.nil? || invoice.account_activity.bank_transaction.nil? ||
- invoice.account_activity.bank_transaction.sum.nil? || invoice.account_activity.bank_transaction.sum != invoice.total
- Rails.logger.info("[DIRECTO] Invoice #{invoice.number} has been skipped")
- next
- end
- counter += 1
-
- num = invoice.number
- paid_at = invoice.account_activity.bank_transaction&.paid_at&.strftime("%Y-%m-%d")
- mappers[num] = invoice
- xml.invoice(
- "SalesAgent" => Setting.directo_sales_agent,
- "Number" => num,
- "InvoiceDate" => invoice.issue_date.strftime("%Y-%m-%d"),
- 'TransactionDate' => paid_at,
- "PaymentTerm" => Setting.directo_receipt_payment_term,
- "Currency" => invoice.currency,
- "CustomerCode"=> invoice.buyer.accounting_customer_code
- ){
- xml.line(
- "ProductID" => Setting.directo_receipt_product_name,
- "Quantity" => 1,
- "UnitPriceWoVAT" => ActionController::Base.helpers.number_with_precision(invoice.subtotal, precision: 2, separator: "."),
- "ProductName" => invoice.order
- )
- }
- end
- }
- end
-
- data = builder.to_xml.gsub("\n",'')
- Rails.logger.info("[Directo] XML request: #{data}")
- response = RestClient::Request.execute(url: ENV['directo_invoice_url'], method: :post, payload: {put: "1", what: "invoice", xmldata: data}, verify_ssl: false)
- Rails.logger.info("[Directo] Directo responded with code: #{response.code}, body: #{response.body}")
- dump_result_to_db(mappers, response.to_s)
- end
-
- STDOUT << "#{Time.zone.now.utc} - Directo receipts sending finished. #{counter} of #{total} are sent\n"
- end
-
- def self.dump_result_to_db mappers, xml
- Nokogiri::XML(xml).css("Result").each do |res|
- obj = mappers[res.attributes["docid"].value.to_i]
- obj.directo_records.create!(response: res.as_json.to_h, invoice_number: obj.number)
- obj.update_columns(in_directo: true)
- Rails.logger.info("[DIRECTO] Invoice #{res.attributes["docid"].value} was pushed and return is #{res.as_json.to_h.inspect}")
- end
- end
-
-
- def self.send_monthly_invoices(debug: false)
- I18n.locale = :et
- month = Time.now - 1.month
- invoices_until = month.end_of_month
- date_format = "%Y-%m-%d"
- invoice_counter= Counter.new
-
- min_directo = Setting.directo_monthly_number_min.presence.try(:to_i)
- max_directo = Setting.directo_monthly_number_max.presence.try(:to_i)
- last_directo = [Setting.directo_monthly_number_last.presence.try(:to_i), min_directo].compact.max || 0
- if max_directo && max_directo <= last_directo
- raise "Directo counter is out of period (max allowed number is smaller than last counter number)"
- end
-
- directo_next = last_directo
- Registrar.where.not(test_registrar: true).find_each do |registrar|
- unless registrar.cash_account
- Rails.logger.info("[DIRECTO] Monthly invoice for registrar #{registrar.id} has been skipped as it doesn't has cash_account")
- next
- end
- counter = Counter.new(1)
- items = {}
- registrar_activities = AccountActivity.where(account_id: registrar.account_ids).where("created_at BETWEEN ? AND ?",month.beginning_of_month, month.end_of_month)
-
- # adding domains items
- registrar_activities.where(activity_type: [AccountActivity::CREATE, AccountActivity::RENEW]).each do |activity|
- price = load_price(activity)
-
- if price.duration.include?('year')
- price.duration.to_i.times do |i|
- year = i+1
- hash = {
- "ProductID" => DOMAIN_TO_PRODUCT[price.zone_name],
- "Unit" => "tk",
- "ProductName" => ".#{price.zone_name} registreerimine: #{price.duration.to_i} aasta#{price.duration.to_i > 1 ? 't' : ''}",
- "UnitPriceWoVAT" => price.price.amount / price.duration.to_i
- }
- hash["StartDate"] = (activity.created_at + (year-1).year).end_of_month.strftime(date_format) if year > 1
- hash["EndDate"] = (activity.created_at + (year-1).year + 1).end_of_month.strftime(date_format) if year > 1
-
- if items.has_key?(hash)
- items[hash]["Quantity"] += 1
- else
- items[hash] = { "RN" => counter.next, "RR" => counter.now - i, "Quantity" => 1 }
- end
- end
- else
- 1.times do |i|
- quantity = price.account_activities
- .where(account_id: registrar.account_ids)
- .where(created_at: month.beginning_of_month..month.end_of_month)
- .where(activity_type: [AccountActivity::CREATE, AccountActivity::RENEW])
- .count
-
- hash = {
- "ProductID" => DOMAIN_TO_PRODUCT[price.zone_name],
- "Unit" => "tk",
- "ProductName" => ".#{price.zone_name} registreerimine: #{price.duration.to_i} kuud",
- "UnitPriceWoVAT" => price.price.amount,
- }
-
- if items.has_key?(hash)
- #items[hash]["Quantity"] += 1
- else
- items[hash] = { "RN" => counter.next, "RR" => counter.now - i, "Quantity" => quantity }
- end
- end
- end
-
-
- end
-
- #adding prepaiments
- if items.any?
- total = 0
- items.each{ |key, val| total += val["Quantity"] * key["UnitPriceWoVAT"] }
- hash = {"ProductID" => Setting.directo_receipt_product_name, "Unit" => "tk", "ProductName" => "Domeenide ettemaks", "UnitPriceWoVAT"=>total}
- items[hash] = {"RN"=>counter.next, "RR" => counter.now, "Quantity"=> -1}
- end
-
- # generating XML
- if items.any?
- directo_next += 1
- invoice_counter.next
-
- builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
- xml.invoices{
- xml.invoice("Number" =>directo_next,
- "InvoiceDate" =>invoices_until.strftime(date_format),
- "PaymentTerm" =>Setting.directo_receipt_payment_term,
- "CustomerCode"=>registrar.accounting_customer_code,
- "Language" =>"",
- "Currency" =>registrar_activities.first.currency,
- "SalesAgent" =>Setting.directo_sales_agent){
- xml.line("RN" => 1, "RR"=>1, "ProductName"=> "Domeenide registreerimine - #{I18n.l(invoices_until, format: "%B %Y").titleize}")
- items.each do |line, val|
- xml.line(val.merge(line))
- end
- }
- }
- end
-
- data = builder.to_xml.gsub("\n",'')
- Rails.logger.info("[Directo] XML request: #{data}")
-
- if debug
- STDOUT << "#{Time.zone.now.utc} - Directo xml had to be sent #{data}\n"
- else
- response = RestClient::Request.execute(url: ENV['directo_invoice_url'], method: :post, payload: {put: "1", what: "invoice", xmldata: data}, verify_ssl: false)
- Rails.logger.info("[Directo] Directo responded with code: #{response.code}, body: #{response.body}")
- response = response.to_s
-
- Setting.directo_monthly_number_last = directo_next
- Nokogiri::XML(response).css("Result").each do |res|
- Directo.create!(request: data, response: res.as_json.to_h, invoice_number: directo_next)
- Rails.logger.info("[DIRECTO] Invoice #{res.attributes["docid"].value} was pushed and return is #{res.as_json.to_h.inspect}")
- end
- end
- else
- Rails.logger.info("[DIRECTO] Registrar #{registrar.id} has nothing to be sent to Directo")
- end
-
- end
- STDOUT << "#{Time.zone.now.utc} - Directo invoices sending finished. #{invoice_counter.now} are sent\n"
- end
-
- def self.load_price(account_activity)
- @pricelists ||= {}
- return @pricelists[account_activity.price_id] if @pricelists.has_key?(account_activity.price_id)
- @pricelists[account_activity.price_id] = account_activity.price
- end
end
diff --git a/app/models/dnskey.rb b/app/models/dnskey.rb
index 922844874..c0f3f7491 100644
--- a/app/models/dnskey.rb
+++ b/app/models/dnskey.rb
@@ -9,10 +9,16 @@ class Dnskey < ApplicationRecord
validate :validate_protocol
validate :validate_flags
- before_save -> { generate_digest if public_key_changed? && !ds_digest_changed? }
+ before_save lambda {
+ generate_digest if will_save_change_to_public_key? && !will_save_change_to_ds_digest?
+ }
before_save lambda {
- if (public_key_changed? || flags_changed? || alg_changed? || protocol_changed?) && !ds_key_tag_changed?
+ if (will_save_change_to_public_key? ||
+ will_save_change_to_flags? ||
+ will_save_change_to_alg? ||
+ will_save_change_to_protocol?) &&
+ !will_save_change_to_ds_key_tag?
generate_ds_key_tag
end
}
diff --git a/app/models/domain.rb b/app/models/domain.rb
index d6545284d..f21317b70 100644
--- a/app/models/domain.rb
+++ b/app/models/domain.rb
@@ -10,8 +10,6 @@ class Domain < ApplicationRecord
include Concerns::Domain::RegistryLockable
include Concerns::Domain::Releasable
- has_paper_trail class_name: "DomainVersion", meta: { children: :children_log }
-
attr_accessor :roles
attr_accessor :legal_document_id
@@ -73,12 +71,13 @@ class Domain < ApplicationRecord
before_update :manage_statuses
def manage_statuses
- return unless registrant_id_changed? # rollback has not yet happened
+ return unless will_save_change_to_registrant_id? # rollback has not yet happened
+
pending_update! if registrant_verification_asked?
true
end
- after_commit :update_whois_record, unless: 'domain_name.at_auction?'
+ after_commit :update_whois_record, unless: -> { domain_name.at_auction? }
after_create :update_reserved_domains
def update_reserved_domains
@@ -486,9 +485,9 @@ class Domain < ApplicationRecord
self.delete_date = nil
when DomainStatus::SERVER_MANUAL_INZONE # removal causes server hold to set
self.outzone_at = Time.zone.now if force_delete_scheduled?
- when DomainStatus::DomainStatus::EXPIRED # removal causes server hold to set
+ when DomainStatus::EXPIRED # removal causes server hold to set
self.outzone_at = self.expire_time + 15.day
- when DomainStatus::DomainStatus::SERVER_HOLD # removal causes server hold to set
+ when DomainStatus::SERVER_HOLD # removal causes server hold to set
self.outzone_at = nil
end
end
@@ -547,7 +546,7 @@ class Domain < ApplicationRecord
activate if nameservers.reject(&:marked_for_destruction?).size >= Setting.ns_min_count
end
- cancel_force_delete if force_delete_scheduled? && registrant_id_changed?
+ cancel_force_delete if force_delete_scheduled? && will_save_change_to_registrant_id?
if statuses.empty? && valid?
statuses << DomainStatus::OK
diff --git a/app/models/domain_status.rb b/app/models/domain_status.rb
index fba75737c..4b1c49916 100644
--- a/app/models/domain_status.rb
+++ b/app/models/domain_status.rb
@@ -1,7 +1,5 @@
class DomainStatus < ApplicationRecord
- include Versions # version/domain_status_version.rb
include EppErrors
-
belongs_to :domain
# Requests to delete the object MUST be rejected.
diff --git a/app/models/epp/contact.rb b/app/models/epp/contact.rb
index 742f0339f..fa488d9e1 100644
--- a/app/models/epp/contact.rb
+++ b/app/models/epp/contact.rb
@@ -182,7 +182,7 @@ class Epp::Contact < Contact
self.attributes = at
- email_changed = email_changed?
+ email_changed = will_save_change_to_email?
old_email = email_was
updated = save
diff --git a/app/models/invoice.rb b/app/models/invoice.rb
index 7f1dea825..a130a90ff 100644
--- a/app/models/invoice.rb
+++ b/app/models/invoice.rb
@@ -2,11 +2,13 @@ class Invoice < ApplicationRecord
include Versions
include Concerns::Invoice::Cancellable
include Concerns::Invoice::Payable
+ include Concerns::Invoice::BookKeeping
belongs_to :buyer, class_name: 'Registrar'
has_one :account_activity
has_many :items, class_name: 'InvoiceItem', dependent: :destroy
has_many :directo_records, as: :item, class_name: 'Directo'
+ has_many :payment_orders
accepts_nested_attributes_for :items
@@ -70,7 +72,7 @@ class Invoice < ApplicationRecord
Country.new(buyer_country_code)
end
-# order is used for directo/banklink description
+ # order is used for directo/banklink description
def order
"Order nr. #{number}"
end
@@ -102,6 +104,14 @@ class Invoice < ApplicationRecord
generator.generate
end
+ def do_not_send_e_invoice?
+ e_invoice_sent? || cancelled? || paid?
+ end
+
+ def e_invoice_sent?
+ e_invoice_sent_at.present?
+ end
+
private
def apply_default_buyer_vat_no
@@ -111,4 +121,4 @@ class Invoice < ApplicationRecord
def calculate_total
self.total = subtotal + vat_amount
end
-end
\ No newline at end of file
+end
diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb
index bf76868dc..3ddf1d1c5 100644
--- a/app/models/nameserver.rb
+++ b/app/models/nameserver.rb
@@ -48,7 +48,7 @@ class Nameserver < ApplicationRecord
[:ipv6, :invalid, { value: { obj: 'hostAddr', val: ipv6 } }]
],
'2003' => [
- [:ipv4, :blank]
+ %i[base ip_required],
]
}
end
@@ -83,6 +83,7 @@ class Nameserver < ApplicationRecord
def glue_record_required?
return unless hostname? && domain
+
DomainName(hostname).domain == domain.name
end
diff --git a/app/models/payment_order.rb b/app/models/payment_order.rb
new file mode 100644
index 000000000..4317abb38
--- /dev/null
+++ b/app/models/payment_order.rb
@@ -0,0 +1,102 @@
+class PaymentOrder < ApplicationRecord
+ include Versions
+ include ActionView::Helpers::NumberHelper
+
+ PAYMENT_INTERMEDIARIES = ENV['payments_intermediaries'].to_s.strip.split(', ').freeze
+ PAYMENT_BANKLINK_BANKS = ENV['payments_banks'].to_s.strip.split(', ').freeze
+ INTERNAL_PAYMENT_METHODS = %w[admin_payment system_payment].freeze
+ PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS,
+ INTERNAL_PAYMENT_METHODS].flatten.freeze
+ CUSTOMER_PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS].flatten.freeze
+
+ belongs_to :invoice, optional: false
+
+ validate :invoice_cannot_be_already_paid, on: :create
+ validate :supported_payment_method
+
+ enum status: { issued: 'issued', paid: 'paid', cancelled: 'cancelled',
+ failed: 'failed' }
+
+ attr_accessor :return_url, :response_url
+
+ def self.supported_methods
+ supported = []
+
+ PAYMENT_METHODS.each do |method|
+ class_name = ('PaymentOrders::' + method.camelize).constantize
+ raise(NoMethodError, class_name) unless class_name < PaymentOrder
+
+ supported << class_name
+ end
+
+ supported
+ end
+
+ def self.new_with_type(type:, invoice:)
+ channel = ('PaymentOrders::' + type.camelize).constantize
+
+ PaymentOrder.new(type: channel, invoice: invoice)
+ end
+
+ # Name of configuration namespace
+ def self.config_namespace_name; end
+
+ def supported_payment_method
+ return if PaymentOrder.supported_method?(type)
+
+ errors.add(:type, 'is not supported')
+ end
+
+ def invoice_cannot_be_already_paid
+ return unless invoice&.paid?
+
+ errors.add(:invoice, 'is already paid')
+ end
+
+ def self.supported_method?(name, shortname: false)
+ some_class = if shortname
+ ('PaymentOrders::' + name.camelize).constantize
+ else
+ name.constantize
+ end
+ supported_methods.include? some_class
+ rescue NameError
+ false
+ end
+
+ def base_transaction(sum:, paid_at:, buyer_name:)
+ BankTransaction.new(
+ description: invoice.order,
+ reference_no: invoice.reference_no,
+ currency: invoice.currency,
+ iban: invoice.seller_iban,
+ sum: sum,
+ paid_at: paid_at,
+ buyer_name: buyer_name
+ )
+ end
+
+ def complete_transaction
+ return NoMethodError unless payment_received?
+
+ paid!
+ transaction = composed_transaction
+ transaction.save! && transaction.bind_invoice(invoice.number)
+ return unless transaction.errors.any?
+
+ worded_errors = 'Failed to bind. '
+ transaction.errors.full_messages.each do |err|
+ worded_errors << "#{err}, "
+ end
+
+ update!(notes: worded_errors)
+ end
+
+ def channel
+ type.gsub('PaymentOrders::', '')
+ end
+
+ def form_url
+ ENV["payments_#{self.class.config_namespace_name}_url"]
+ end
+end
diff --git a/app/models/payment_orders.rb b/app/models/payment_orders.rb
deleted file mode 100644
index 921af0cd4..000000000
--- a/app/models/payment_orders.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-module PaymentOrders
- PAYMENT_INTERMEDIARIES = ENV['payments_intermediaries'].to_s.strip.split(', ').freeze
- PAYMENT_BANKLINK_BANKS = ENV['payments_banks'].to_s.strip.split(', ').freeze
- PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS].flatten.freeze
-
- def self.create_with_type(type, invoice, opts = {})
- raise ArgumentError unless PAYMENT_METHODS.include?(type)
-
- if PAYMENT_BANKLINK_BANKS.include?(type)
- BankLink.new(type, invoice, opts)
- elsif type == 'every_pay'
- EveryPay.new(type, invoice, opts)
- end
- end
-end
diff --git a/app/models/payment_orders/admin_payment.rb b/app/models/payment_orders/admin_payment.rb
new file mode 100644
index 000000000..05ae061fb
--- /dev/null
+++ b/app/models/payment_orders/admin_payment.rb
@@ -0,0 +1,9 @@
+module PaymentOrders
+ class AdminPayment < PaymentOrder
+ CONFIG_NAMESPACE = 'admin_payment'.freeze
+
+ def self.config_namespace_name
+ CONFIG_NAMESPACE
+ end
+ end
+end
diff --git a/app/models/payment_orders/bank_link.rb b/app/models/payment_orders/bank_link.rb
index 1e4c2785a..c8714d245 100644
--- a/app/models/payment_orders/bank_link.rb
+++ b/app/models/payment_orders/bank_link.rb
@@ -1,44 +1,44 @@
module PaymentOrders
- class BankLink < Base
- BANK_LINK_VERSION = '008'
+ class BankLink < PaymentOrder
+ BANK_LINK_VERSION = '008'.freeze
- NEW_TRANSACTION_SERVICE_NUMBER = '1012'
- SUCCESSFUL_PAYMENT_SERVICE_NUMBER = '1111'
- CANCELLED_PAYMENT_SERVICE_NUMBER = '1911'
+ NEW_TRANSACTION_SERVICE_NUMBER = '1012'.freeze
+ SUCCESSFUL_PAYMENT_SERVICE_NUMBER = '1111'.freeze
+ CANCELLED_PAYMENT_SERVICE_NUMBER = '1911'.freeze
- NEW_MESSAGE_KEYS = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_STAMP VK_AMOUNT
+ NEW_MESSAGE_KEYS = %w[VK_SERVICE VK_VERSION VK_SND_ID VK_STAMP VK_AMOUNT
VK_CURR VK_REF VK_MSG VK_RETURN VK_CANCEL
- VK_DATETIME).freeze
- SUCCESS_MESSAGE_KEYS = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP
+ VK_DATETIME].freeze
+ SUCCESS_MESSAGE_KEYS = %w[VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP
VK_T_NO VK_AMOUNT VK_CURR VK_REC_ACC VK_REC_NAME
VK_SND_ACC VK_SND_NAME VK_REF VK_MSG
- VK_T_DATETIME).freeze
- CANCEL_MESSAGE_KEYS = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP
- VK_REF VK_MSG).freeze
+ VK_T_DATETIME].freeze
+ CANCEL_MESSAGE_KEYS = %w[VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP
+ VK_REF VK_MSG].freeze
def form_fields
hash = {}
- hash["VK_SERVICE"] = NEW_TRANSACTION_SERVICE_NUMBER
- hash["VK_VERSION"] = BANK_LINK_VERSION
- hash["VK_SND_ID"] = seller_account
- hash["VK_STAMP"] = invoice.number
- hash["VK_AMOUNT"] = number_with_precision(invoice.total, precision: 2, separator: ".")
- hash["VK_CURR"] = invoice.currency
- hash["VK_REF"] = ""
- hash["VK_MSG"] = invoice.order
- hash["VK_RETURN"] = return_url
- hash["VK_CANCEL"] = return_url
- hash["VK_DATETIME"] = Time.zone.now.strftime("%Y-%m-%dT%H:%M:%S%z")
- hash["VK_MAC"] = calc_mac(hash)
- hash["VK_ENCODING"] = "UTF-8"
- hash["VK_LANG"] = "ENG"
+ hash['VK_SERVICE'] = NEW_TRANSACTION_SERVICE_NUMBER
+ hash['VK_VERSION'] = BANK_LINK_VERSION
+ hash['VK_SND_ID'] = seller_account
+ hash['VK_STAMP'] = invoice.number
+ hash['VK_AMOUNT'] = number_with_precision(invoice.total, precision: 2, separator: ".")
+ hash['VK_CURR'] = invoice.currency
+ hash['VK_REF'] = ''
+ hash['VK_MSG'] = invoice.order
+ hash['VK_RETURN'] = return_url
+ hash['VK_CANCEL'] = return_url
+ hash['VK_DATETIME'] = Time.zone.now.strftime('%Y-%m-%dT%H:%M:%S%z')
+ hash['VK_MAC'] = calc_mac(hash)
+ hash['VK_ENCODING'] = 'UTF-8'
+ hash['VK_LANG'] = 'ENG'
hash
end
def valid_response_from_intermediary?
return false unless response
- case response["VK_SERVICE"]
+ case response['VK_SERVICE']
when SUCCESSFUL_PAYMENT_SERVICE_NUMBER
valid_successful_transaction?
when CANCELLED_PAYMENT_SERVICE_NUMBER
@@ -48,29 +48,31 @@ module PaymentOrders
end
end
- def complete_transaction
- return unless valid_successful_transaction?
+ def payment_received?
+ valid_response_from_intermediary? && settled_payment?
+ end
- transaction = compose_or_find_transaction
+ def create_failure_report
+ notes = "User failed to make payment. Bank responded with code #{response['VK_SERVICE']}"
+ status = 'cancelled'
+ update!(notes: notes, status: status)
+ end
- transaction.sum = response['VK_AMOUNT']
- transaction.bank_reference = response['VK_T_NO']
- transaction.buyer_bank_code = response["VK_SND_ID"]
- transaction.buyer_iban = response["VK_SND_ACC"]
- transaction.buyer_name = response["VK_SND_NAME"]
- transaction.paid_at = Time.parse(response["VK_T_DATETIME"])
+ def composed_transaction
+ paid_at = Time.parse(response['VK_T_DATETIME'])
+ transaction = base_transaction(sum: response['VK_AMOUNT'],
+ paid_at: paid_at,
+ buyer_name: response['VK_SND_NAME'])
- transaction.save!
- transaction.bind_invoice(invoice.number)
- if transaction.errors.empty?
- Rails.logger.info("Invoice ##{invoice.number} was marked as paid")
- else
- Rails.logger.error("Failed to bind invoice ##{invoice.number}")
- end
+ transaction.bank_reference = response['VK_T_NO']
+ transaction.buyer_bank_code = response['VK_SND_ID']
+ transaction.buyer_iban = response['VK_SND_ACC']
+
+ transaction
end
def settled_payment?
- response["VK_SERVICE"] == SUCCESSFUL_PAYMENT_SERVICE_NUMBER
+ response['VK_SERVICE'] == SUCCESSFUL_PAYMENT_SERVICE_NUMBER
end
private
@@ -89,17 +91,15 @@ module PaymentOrders
def valid_amount?
source = number_with_precision(
- BigDecimal.new(response["VK_AMOUNT"]), precision: 2, separator: "."
- )
- target = number_with_precision(
- invoice.total, precision: 2, separator: "."
+ BigDecimal(response['VK_AMOUNT']), precision: 2, separator: '.'
)
+ target = number_with_precision(invoice.total, precision: 2, separator: '.')
source == target
end
def valid_currency?
- invoice.currency == response["VK_CURR"]
+ invoice.currency == response['VK_CURR']
end
def sign(data)
@@ -117,7 +117,7 @@ module PaymentOrders
def valid_mac?(hash, keys)
data = keys.map { |element| prepend_size(hash[element]) }.join
- verify_mac(data, hash["VK_MAC"])
+ verify_mac(data, hash['VK_MAC'])
end
def verify_mac(data, mac)
@@ -126,22 +126,22 @@ module PaymentOrders
end
def prepend_size(value)
- value = (value || "").to_s.strip
- string = ""
+ value = (value || '').to_s.strip
+ string = ''
string << format("%03i", value.size)
string << value
end
def seller_account
- ENV["payments_#{type}_seller_account"]
+ ENV["payments_#{self.class.config_namespace_name}_seller_account"]
end
def seller_certificate
- ENV["payments_#{type}_seller_private"]
+ ENV["payments_#{self.class.config_namespace_name}_seller_private"]
end
def bank_certificate
- ENV["payments_#{type}_bank_certificate"]
+ ENV["payments_#{self.class.config_namespace_name}_bank_certificate"]
end
end
end
diff --git a/app/models/payment_orders/base.rb b/app/models/payment_orders/base.rb
deleted file mode 100644
index 772f33ba5..000000000
--- a/app/models/payment_orders/base.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-module PaymentOrders
- class Base
- include ActionView::Helpers::NumberHelper
-
- attr_reader :type,
- :invoice,
- :return_url,
- :response_url,
- :response
-
- def initialize(type, invoice, opts = {})
- @type = type
- @invoice = invoice
- @return_url = opts[:return_url]
- @response_url = opts[:response_url]
- @response = opts[:response]
- end
-
- def create_transaction
- transaction = BankTransaction.where(description: invoice.order).first_or_initialize(
- reference_no: invoice.reference_no,
- currency: invoice.currency,
- iban: invoice.seller_iban
- )
-
- transaction.save!
- end
-
- def compose_or_find_transaction
- transaction = BankTransaction.find_by(base_transaction_params)
-
- # Transaction already autobinded (possibly) invalid invoice
- if transaction.binded?
- Rails.logger.info("Transaction #{transaction.id} is already binded")
- Rails.logger.info('Creating new BankTransaction record.')
-
- transaction = new_base_transaction
- end
-
- transaction
- end
-
- def new_base_transaction
- BankTransaction.new(base_transaction_params)
- end
-
- def base_transaction_params
- {
- description: invoice.order,
- currency: invoice.currency,
- iban: invoice.seller_iban,
- }
- end
-
- def form_url
- ENV["payments_#{type}_url"]
- end
- end
-end
diff --git a/app/models/payment_orders/every_pay.rb b/app/models/payment_orders/every_pay.rb
index a866ba972..2695c20e0 100644
--- a/app/models/payment_orders/every_pay.rb
+++ b/app/models/payment_orders/every_pay.rb
@@ -1,9 +1,15 @@
module PaymentOrders
- class EveryPay < Base
- USER = ENV['payments_every_pay_api_user'].freeze
- KEY = ENV['payments_every_pay_api_key'].freeze
- ACCOUNT_ID = ENV['payments_every_pay_seller_account'].freeze
- SUCCESSFUL_PAYMENT = %w(settled authorized).freeze
+ class EveryPay < PaymentOrder
+ USER = ENV['payments_every_pay_api_user']
+ KEY = ENV['payments_every_pay_api_key']
+ ACCOUNT_ID = ENV['payments_every_pay_seller_account']
+ SUCCESSFUL_PAYMENT = %w[settled authorized].freeze
+
+ CONFIG_NAMESPACE = 'every_pay'.freeze
+
+ def self.config_namespace_name
+ CONFIG_NAMESPACE
+ end
def form_fields
base_json = base_params
@@ -25,25 +31,23 @@ module PaymentOrders
end
def settled_payment?
- SUCCESSFUL_PAYMENT.include?(response[:payment_state])
+ SUCCESSFUL_PAYMENT.include?(response['payment_state'])
end
- def complete_transaction
- return unless valid_response_from_intermediary? && settled_payment?
+ def payment_received?
+ valid_response_from_intermediary? && settled_payment?
+ end
- transaction = compose_or_find_transaction
+ def composed_transaction
+ base_transaction(sum: response['amount'],
+ paid_at: Date.strptime(response['timestamp'], '%s'),
+ buyer_name: response['cc_holder_name'])
+ end
- transaction.sum = response[:amount]
- transaction.paid_at = Date.strptime(response[:timestamp], '%s')
- transaction.buyer_name = response[:cc_holder_name]
-
- transaction.save!
- transaction.bind_invoice(invoice.number)
- if transaction.errors.empty?
- Rails.logger.info("Invoice ##{invoice.number} marked as paid")
- else
- Rails.logger.error("Failed to bind invoice ##{invoice.number}")
- end
+ def create_failure_report
+ notes = "User failed to make valid payment. Payment state: #{response['payment_state']}"
+ status = 'cancelled'
+ update!(notes: notes, status: status)
end
private
@@ -63,24 +67,27 @@ module PaymentOrders
end
def valid_hmac?
- hmac_fields = response[:hmac_fields].split(',')
+ hmac_fields = response['hmac_fields'].split(',')
hmac_hash = {}
hmac_fields.map do |field|
- symbol = field.to_sym
- hmac_hash[symbol] = response[symbol]
+ hmac_hash[field] = response[field]
end
hmac_string = hmac_hash.map { |key, _v| "#{key}=#{hmac_hash[key]}" }.join('&')
expected_hmac = OpenSSL::HMAC.hexdigest('sha1', KEY, hmac_string)
- expected_hmac == response[:hmac]
+ expected_hmac == response['hmac']
+ rescue NoMethodError
+ false
end
def valid_amount?
- invoice.total == BigDecimal.new(response[:amount])
+ return false unless response.key? 'amount'
+
+ invoice.total == BigDecimal(response['amount'])
end
def valid_account?
- response[:account_id] == ACCOUNT_ID
+ response['account_id'] == ACCOUNT_ID
end
end
end
diff --git a/app/models/payment_orders/lhv.rb b/app/models/payment_orders/lhv.rb
new file mode 100644
index 000000000..4c9f59c4a
--- /dev/null
+++ b/app/models/payment_orders/lhv.rb
@@ -0,0 +1,7 @@
+module PaymentOrders
+ class Lhv < BankLink
+ def self.config_namespace_name
+ 'lhv'
+ end
+ end
+end
diff --git a/app/models/payment_orders/seb.rb b/app/models/payment_orders/seb.rb
new file mode 100644
index 000000000..878d877a7
--- /dev/null
+++ b/app/models/payment_orders/seb.rb
@@ -0,0 +1,7 @@
+module PaymentOrders
+ class Seb < BankLink
+ def self.config_namespace_name
+ 'seb'
+ end
+ end
+end
diff --git a/app/models/payment_orders/swed.rb b/app/models/payment_orders/swed.rb
new file mode 100644
index 000000000..ff3aca3d1
--- /dev/null
+++ b/app/models/payment_orders/swed.rb
@@ -0,0 +1,7 @@
+module PaymentOrders
+ class Swed < BankLink
+ def self.config_namespace_name
+ 'swed'
+ end
+ end
+end
diff --git a/app/models/payment_orders/system_payment.rb b/app/models/payment_orders/system_payment.rb
new file mode 100644
index 000000000..47c75ebe3
--- /dev/null
+++ b/app/models/payment_orders/system_payment.rb
@@ -0,0 +1,9 @@
+module PaymentOrders
+ class SystemPayment < PaymentOrder
+ CONFIG_NAMESPACE = 'system_payment'.freeze
+
+ def self.config_namespace_name
+ CONFIG_NAMESPACE
+ end
+ end
+end
diff --git a/app/models/registrar.rb b/app/models/registrar.rb
index 8f41d62ca..c3522859e 100644
--- a/app/models/registrar.rb
+++ b/app/models/registrar.rb
@@ -1,5 +1,6 @@
class Registrar < ApplicationRecord
include Versions # version/registrar_version.rb
+ include Concerns::Registrar::BookKeeping
has_many :domains, dependent: :restrict_with_error
has_many :contacts, dependent: :restrict_with_error
@@ -21,9 +22,9 @@ class Registrar < ApplicationRecord
validates :reference_no, format: Billing::ReferenceNo::REGEXP
validate :forbid_special_code
- validates :vat_rate, presence: true, if: 'vat_liable_in_foreign_country? && vat_no.blank?'
+ validates :vat_rate, presence: true, if: -> { vat_liable_in_foreign_country? && vat_no.blank? }
validates :vat_rate, absence: true, if: :vat_liable_locally?
- validates :vat_rate, absence: true, if: 'vat_liable_in_foreign_country? && vat_no?'
+ validates :vat_rate, absence: true, if: -> { vat_liable_in_foreign_country? && vat_no? }
validates :vat_rate, numericality: { greater_than_or_equal_to: 0, less_than: 100 },
allow_nil: true
@@ -33,7 +34,7 @@ class Registrar < ApplicationRecord
after_initialize :set_defaults
validates :email, email_format: { message: :invalid },
- allow_blank: true, if: proc { |c| c.email_changed? }
+ allow_blank: true, if: proc { |c| c.will_save_change_to_email? }
validates :billing_email, email_format: { message: :invalid }, allow_blank: true
alias_attribute :contact_email, :email
@@ -99,9 +100,7 @@ class Registrar < ApplicationRecord
}
]
)
-
- e_invoice = invoice.to_e_invoice
- e_invoice.deliver
+ SendEInvoiceJob.enqueue(invoice.id)
invoice
end
diff --git a/app/models/version/payment_order_version.rb b/app/models/version/payment_order_version.rb
new file mode 100644
index 000000000..e556f1021
--- /dev/null
+++ b/app/models/version/payment_order_version.rb
@@ -0,0 +1,4 @@
+class PaymentOrderVersion < PaperTrail::Version
+ self.table_name = :log_payment_orders
+ self.sequence_name = :log_payment_orders_id_seq
+end
diff --git a/app/views/admin/invoices/show.haml b/app/views/admin/invoices/show.haml
index e3627c158..d0450469f 100644
--- a/app/views/admin/invoices/show.haml
+++ b/app/views/admin/invoices/show.haml
@@ -21,3 +21,5 @@
.col-md-6= render 'registrar/invoices/partials/buyer'
.row
.col-md-12= render 'registrar/invoices/partials/items'
+.row
+ .col-md-12= render 'registrar/invoices/partials/payment_orders'
diff --git a/app/views/layouts/admin/base.haml b/app/views/layouts/admin/base.haml
index 792a8cc0b..928629ce6 100644
--- a/app/views/layouts/admin/base.haml
+++ b/app/views/layouts/admin/base.haml
@@ -32,5 +32,5 @@
.footer.text-right
Version
- = CURRENT_COMMIT_HASH
+ = current_commit_link
= javascript_include_tag 'admin-manifest', async: true
diff --git a/app/views/layouts/registrant/application.html.erb b/app/views/layouts/registrant/application.html.erb
index 66fdf3e16..c5290b70f 100644
--- a/app/views/layouts/registrant/application.html.erb
+++ b/app/views/layouts/registrant/application.html.erb
@@ -76,7 +76,7 @@
Version
- <%= CURRENT_COMMIT_HASH %>
+ <%= current_commit_link %>
diff --git a/app/views/layouts/registrar/base.html.erb b/app/views/layouts/registrar/base.html.erb
index 4d4f1b972..5881dd400 100644
--- a/app/views/layouts/registrar/base.html.erb
+++ b/app/views/layouts/registrar/base.html.erb
@@ -54,7 +54,7 @@
Version
- <%= CURRENT_COMMIT_HASH %>
+ <%= current_commit_link %>
diff --git a/app/views/layouts/registrar/sessions.html.erb b/app/views/layouts/registrar/sessions.html.erb
index 3cb345ef9..ace645199 100644
--- a/app/views/layouts/registrar/sessions.html.erb
+++ b/app/views/layouts/registrar/sessions.html.erb
@@ -44,7 +44,7 @@
Version
- <%= CURRENT_COMMIT_HASH %>
+ <%= current_commit_link %>
diff --git a/app/views/registrar/domains/info.html.erb b/app/views/registrar/domains/info.html.erb
index 1fcfc23c3..e88882233 100644
--- a/app/views/registrar/domains/info.html.erb
+++ b/app/views/registrar/domains/info.html.erb
@@ -6,6 +6,10 @@
class: 'btn btn-default') %>
<%= link_to(t(:delete), delete_registrar_domains_path(domain_name: params[:domain_name]),
class: 'btn btn-default') %>
+ <% if @client_holded %>
+ <%= link_to(t(:remove_client_hold), remove_hold_registrar_domains_path(domain_name: params[:domain_name]),
+ class: 'btn btn-default') %>
+ <% end %>
<% else %>
<%= link_to t('.transfer_btn'), new_registrar_domain_transfer_path(domain_name: params[:domain_name]),
class: 'btn btn-default' %>
diff --git a/app/views/registrar/invoices/partials/_payment_orders.haml b/app/views/registrar/invoices/partials/_payment_orders.haml
new file mode 100644
index 000000000..d418ea1ac
--- /dev/null
+++ b/app/views/registrar/invoices/partials/_payment_orders.haml
@@ -0,0 +1,19 @@
+%h4= "Payment Orders"
+%hr
+.table-responsive
+ %table.table.table-hover.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-1'}= "#"
+ %th{class: 'col-xs-1'}= "Channel"
+ %th{class: 'col-xs-2'}= "Status"
+ %th{class: 'col-xs-3'}= "Initiated"
+ %th{class: 'col-xs-4'}= "Notes"
+ %tbody
+ - @invoice.payment_orders.each do |payment_order|
+ %tr
+ %td= payment_order.id
+ %td= payment_order.channel
+ %td= payment_order.status
+ %td= payment_order.created_at
+ %td= payment_order.notes
diff --git a/app/views/registrar/invoices/show.haml b/app/views/registrar/invoices/show.haml
index 66a025eaf..5e6104091 100644
--- a/app/views/registrar/invoices/show.haml
+++ b/app/views/registrar/invoices/show.haml
@@ -17,4 +17,4 @@
- if @invoice.payable?
.row.semifooter
- .col-md-6-offset-6.text-right= render 'registrar/invoices/partials/banklinks', locals: { payment_channels: PaymentOrders::PAYMENT_METHODS }
+ .col-md-6-offset-6.text-right= render 'registrar/invoices/partials/banklinks', locals: { payment_channels: PaymentOrder::CUSTOMER_PAYMENT_METHODS }
diff --git a/app/views/registrar/payments/pay.html.haml b/app/views/registrar/payments/pay.html.haml
index 8e759f9ea..dd3fc982f 100644
--- a/app/views/registrar/payments/pay.html.haml
+++ b/app/views/registrar/payments/pay.html.haml
@@ -2,8 +2,8 @@
= t('registrar.invoices.redirected_to_intermediary')
.payment-form
- = form_tag @payment.form_url, method: :post do
- - @payment.form_fields.each do |k, v|
+ = form_tag @payment_order.form_url, method: :post do
+ - @payment_order.form_fields.each do |k, v|
= hidden_field_tag k, v
= submit_tag t('registrar.invoices.go_to_intermediary')
diff --git a/app/views/registrar/xml_consoles/epp_requests/domain/client_hold.xml b/app/views/registrar/xml_consoles/epp_requests/domain/client_hold.xml
new file mode 100644
index 000000000..fcafec538
--- /dev/null
+++ b/app/views/registrar/xml_consoles/epp_requests/domain/client_hold.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ example.ee
+
+
+
+
+
+ timo-1579351654
+
+
diff --git a/app/views/registrar/xml_consoles/show.haml b/app/views/registrar/xml_consoles/show.haml
index f96b67738..bb66116ee 100644
--- a/app/views/registrar/xml_consoles/show.haml
+++ b/app/views/registrar/xml_consoles/show.haml
@@ -29,6 +29,9 @@
,
%a.js-load-xml{href: 'javascript:void(0)', data: {obj: 'domain', epp_action: 'delete'}}
Delete
+ ,
+ %a.js-load-xml{href: 'javascript:void(0)', data: {obj: 'domain', epp_action: 'client_hold'}}
+ Remove Client Hold
%h4 Poll
%a.js-load-xml{href: 'javascript:void(0)', data: {obj: 'poll', epp_action: 'poll'}}
diff --git a/bin/bundle b/bin/bundle
index 66e9889e8..8bfc37be6 100755
--- a/bin/bundle
+++ b/bin/bundle
@@ -1,3 +1,3 @@
#!/usr/bin/env ruby
-ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __dir__)
load Gem.bin_path('bundler', 'bundle')
diff --git a/bin/setup b/bin/setup
index b3067cf22..ab3c84d9b 100755
--- a/bin/setup
+++ b/bin/setup
@@ -1,33 +1,38 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
+
require 'pathname'
-require 'fileutils'
+include FileUtils
# path to your application root.
-APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
-
+APP_ROOT = Pathname.new File.expand_path('../../', __dir__)
def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
end
-Dir.chdir APP_ROOT do
+chdir APP_ROOT do
+ # This script is a starting point to setup your application.
+ # Add necessary setup steps to this file.
- puts '== Installing dependencies with bundler =='
+ puts '== Installing dependencies =='
system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install')
- puts "\n== Copying sample development database config files =="
+ # Install JavaScript dependencies if using Yarn
+ # system('bin/yarn')
+
+ puts "\n== Copying sample files =="
unless File.exist?('config/database.yml')
- system! 'cp config/database-example-development.yml config/database.yml'
+ system! 'cp config/database.yml.sample config/database.yml'
end
puts "\n== Preparing database =="
system! 'bin/rails db:setup'
puts "\n== Removing old logs and tempfiles =="
- system! 'bin/rake log:clear tmp:clear'
+ system! 'bin/rails log:clear tmp:clear'
puts "\n== Restarting application server =="
- system! 'touch tmp/restart.txt'
-
+ system! 'bin/rails restart'
end
diff --git a/bin/update b/bin/update
old mode 100644
new mode 100755
diff --git a/bin/yarn b/bin/yarn
new file mode 100755
index 000000000..adabdd976
--- /dev/null
+++ b/bin/yarn
@@ -0,0 +1,9 @@
+#!/usr/bin/env ruby
+APP_ROOT = File.expand_path('..', __dir__)
+Dir.chdir(APP_ROOT) do
+ exec 'yarnpkg', *ARGV
+rescue Errno::ENOENT
+ $stderr.puts 'Yarn executable was not detected in the system.'
+ $stderr.puts 'Download Yarn at https://yarnpkg.com/en/docs/install'
+ exit 1
+end
diff --git a/config/application.rb b/config/application.rb
index c70ab2111..72b592a3b 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -16,6 +16,7 @@ end
module DomainNameRegistry
class Application < Rails::Application
+ config.load_defaults 5.1
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
diff --git a/config/cable.yml b/config/cable.yml
index 0bbde6f74..858bb1f14 100644
--- a/config/cable.yml
+++ b/config/cable.yml
@@ -7,3 +7,4 @@ test:
production:
adapter: redis
url: redis://localhost:6379/1
+ channel_prefix: domain_name_registry_production
diff --git a/config/environments/production.rb b/config/environments/production.rb
index c2262235d..6e13ea1f7 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -66,7 +66,7 @@ Rails.application.configure do
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
- config.i18n.fallbacks = [I18n.default_locale]
+ config.i18n.fallbacks = true
# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 6913ceb7e..784b48f42 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -1,4 +1,6 @@
+
Rails.application.configure do
+ $VERBOSE = nil
# Settings specified here will take precedence over those in config/application.rb.
# The test environment is used exclusively to run your application's
@@ -30,7 +32,7 @@ Rails.application.configure do
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the stderr.
- config.active_support.deprecation = :stderr
+ config.active_support.deprecation = :silence
# Raises error for missing translations
config.action_view.raise_on_missing_translations = true
diff --git a/config/initializers/airbrake.rb b/config/initializers/airbrake.rb
index 917deb02a..5c1983369 100644
--- a/config/initializers/airbrake.rb
+++ b/config/initializers/airbrake.rb
@@ -3,6 +3,9 @@ Airbrake.configure do |config|
config.project_id = ENV['airbrake_project_id']
config.project_key = ENV['airbrake_project_key']
config.root_directory = Rails.root
+ config.job_stats = false
+ config.query_stats = false
+ config.performance_stats = false
config.logger =
if ENV['RAILS_LOG_TO_STDOUT'].present?
Logger.new(STDOUT, level: Rails.logger.level)
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
index d3b8408d5..ba78ea325 100644
--- a/config/initializers/assets.rb
+++ b/config/initializers/assets.rb
@@ -5,7 +5,7 @@ Rails.application.configure do
config.assets.version = '1.0'
# Add additional assets to the asset load path
- config.assets.paths << Rails.root.join('vendor', 'assets', 'fonts')
+ config.assets.paths << Rails.root.join('vendor', 'assets', 'fonts', 'node_modules')
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
@@ -14,4 +14,5 @@ Rails.application.configure do
config.assets.precompile += %w(admin-manifest.css admin-manifest.js)
config.assets.precompile += %w(registrar-manifest.css registrar-manifest.js)
config.assets.precompile += %w(registrant-manifest.css registrant-manifest.js)
+ config.assets.precompile += %w( admin.js admin.css )
end
diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb
new file mode 100644
index 000000000..d3bcaa5ec
--- /dev/null
+++ b/config/initializers/content_security_policy.rb
@@ -0,0 +1,25 @@
+# Be sure to restart your server when you modify this file.
+
+# Define an application-wide content security policy
+# For further information see the following documentation
+# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
+
+# Rails.application.config.content_security_policy do |policy|
+# policy.default_src :self, :https
+# policy.font_src :self, :https, :data
+# policy.img_src :self, :https, :data
+# policy.object_src :none
+# policy.script_src :self, :https
+# policy.style_src :self, :https
+
+# # Specify URI for violation reports
+# # policy.report_uri "/csp-violation-report-endpoint"
+# end
+
+# If you are using UJS then enable automatic nonce generation
+# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
+
+# Report CSP violations to a specified URI
+# For further information see the following documentation:
+# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
+# Rails.application.config.content_security_policy_report_only = true
diff --git a/config/initializers/current_commit_hash.rb b/config/initializers/current_commit_hash.rb
deleted file mode 100644
index b018b46fd..000000000
--- a/config/initializers/current_commit_hash.rb
+++ /dev/null
@@ -1 +0,0 @@
-CURRENT_COMMIT_HASH = `git rev-parse --short HEAD`
diff --git a/config/initializers/money.rb b/config/initializers/money.rb
index cb476b589..a52ff280d 100644
--- a/config/initializers/money.rb
+++ b/config/initializers/money.rb
@@ -1,4 +1,6 @@
MoneyRails.configure do |config|
# Wrapper for Money#default_currency with additional functionality
config.default_currency = :eur
-end
\ No newline at end of file
+ config.rounding_mode = BigDecimal::ROUND_HALF_EVEN
+ config.locale_backend = :i18n
+end
diff --git a/config/initializers/new_framework_defaults.rb b/config/initializers/new_framework_defaults.rb
index 99b2db3b0..2f9c3c5cb 100644
--- a/config/initializers/new_framework_defaults.rb
+++ b/config/initializers/new_framework_defaults.rb
@@ -6,7 +6,8 @@
#
# Read the Guide for Upgrading Ruby on Rails for more info on each option.
-Rails.application.config.action_controller.raise_on_unfiltered_parameters = true
+# DEPRECATION WARNING: raise_on_unfiltered_parameters is deprecated and has no effect in Rails 5.1.
+#Rails.application.config.action_controller.raise_on_unfiltered_parameters = true
# Enable per-form CSRF tokens. Previous versions had false.
Rails.application.config.action_controller.per_form_csrf_tokens = true
@@ -19,7 +20,9 @@ Rails.application.config.action_controller.forgery_protection_origin_check = tru
ActiveSupport.to_time_preserves_timezone = true
# Do not halt callback chains when a callback returns false. Previous versions had true.
-ActiveSupport.halt_callback_chains_on_return_false = false
+# DEPRECATION WARNING: ActiveSupport.halt_callback_chains_on_return_false= is deprecated and
+# will be removed in Rails 5.2.
+#ActiveSupport.halt_callback_chains_on_return_false = false
# Configure SSL options to enable HSTS with subdomains. Previous versions had false.
Rails.application.config.ssl_options = { hsts: { subdomains: true } }
diff --git a/config/initializers/new_framework_defaults_5_1.rb b/config/initializers/new_framework_defaults_5_1.rb
new file mode 100644
index 000000000..9010abd5c
--- /dev/null
+++ b/config/initializers/new_framework_defaults_5_1.rb
@@ -0,0 +1,14 @@
+# Be sure to restart your server when you modify this file.
+#
+# This file contains migration options to ease your Rails 5.1 upgrade.
+#
+# Once upgraded flip defaults one by one to migrate to the new default.
+#
+# Read the Guide for Upgrading Ruby on Rails for more info on each option.
+
+# Make `form_with` generate non-remote forms.
+Rails.application.config.action_view.form_with_generates_remote_forms = false
+
+# Unknown asset fallback will return the path passed in when the given
+# asset is not present in the asset pipeline.
+# Rails.application.config.assets.unknown_asset_fallback = false
diff --git a/config/initializers/new_framework_defaults_5_2.rb b/config/initializers/new_framework_defaults_5_2.rb
new file mode 100644
index 000000000..c383d072b
--- /dev/null
+++ b/config/initializers/new_framework_defaults_5_2.rb
@@ -0,0 +1,38 @@
+# Be sure to restart your server when you modify this file.
+#
+# This file contains migration options to ease your Rails 5.2 upgrade.
+#
+# Once upgraded flip defaults one by one to migrate to the new default.
+#
+# Read the Guide for Upgrading Ruby on Rails for more info on each option.
+
+# Make Active Record use stable #cache_key alongside new #cache_version method.
+# This is needed for recyclable cache keys.
+# Rails.application.config.active_record.cache_versioning = true
+
+# Use AES-256-GCM authenticated encryption for encrypted cookies.
+# Also, embed cookie expiry in signed or encrypted cookies for increased security.
+#
+# This option is not backwards compatible with earlier Rails versions.
+# It's best enabled when your entire app is migrated and stable on 5.2.
+#
+# Existing cookies will be converted on read then written with the new scheme.
+# Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true
+
+# Use AES-256-GCM authenticated encryption as default cipher for encrypting messages
+# instead of AES-256-CBC, when use_authenticated_message_encryption is set to true.
+# Rails.application.config.active_support.use_authenticated_message_encryption = true
+
+# Add default protection from forgery to ActionController::Base instead of in
+# ApplicationController.
+# Rails.application.config.action_controller.default_protect_from_forgery = true
+
+# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and
+# 'f' after migrating old data.
+# Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
+
+# Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header.
+# Rails.application.config.active_support.use_sha1_digests = true
+
+# Make `form_with` generate id attributes for any generated HTML tags.
+# Rails.application.config.action_view.form_with_generates_ids = true
diff --git a/config/initializers/paper_trail.rb b/config/initializers/paper_trail.rb
new file mode 100644
index 000000000..39a667917
--- /dev/null
+++ b/config/initializers/paper_trail.rb
@@ -0,0 +1 @@
+PaperTrail.config.track_associations = false
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 74040fe98..cf72b1027 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -206,6 +206,7 @@ en:
statuses: 'Statuses'
description: 'Description'
delete: 'Delete'
+ remove_client_hold: 'Remove clientHold'
are_you_sure: 'Are you sure?'
back: 'Back'
new_domain: 'New domain'
@@ -580,6 +581,7 @@ en:
tech: Tech contact
valid: Valid
object_is_not_eligible_for_renewal: 'Object is not eligible for renewal'
+ object_is_not_holded: 'Object is not holded'
bank_statement_desc: 'Import file row will match only when matching following attributes:
ref number
payment amount
invoice number (the first numerical value in comment field).'
create_bank_statement: 'Create bank statement'
create_bank_transaction: 'Create bank transaction'
diff --git a/config/locales/registrar/payments.en.yml b/config/locales/registrar/payments.en.yml
new file mode 100644
index 000000000..9c817e0ea
--- /dev/null
+++ b/config/locales/registrar/payments.en.yml
@@ -0,0 +1,7 @@
+en:
+ registrar:
+ payments:
+ back:
+ payment_successful: 'Thank you! Payment received successfully.'
+ successful_payment_backend_error: 'We received your payment, but something went wrong on our side. Please contact us via email or phone.'
+ payment_not_received: 'Payment was unsuccessful. Please make sure you have enough funds on your account and try again.'
diff --git a/config/locales/registrars.en.yml b/config/locales/registrars.en.yml
index 609f9f94a..c57f2e891 100644
--- a/config/locales/registrars.en.yml
+++ b/config/locales/registrars.en.yml
@@ -1,4 +1,8 @@
en:
+ registrar:
+ invoice_yearly_product_description: '%{tld} registration: %{length} year(s)'
+ invoice_monthly_product_description: '%{tld} registration: %{length} month(s)'
+ monthly_summary_title: 'Domain registrations - %{date}'
activerecord:
errors:
models:
@@ -8,4 +12,4 @@ en:
forbidden: is forbidden
vat_rate:
present: >-
- must be blank when a registrar is VAT-registered in the same country as registry
\ No newline at end of file
+ must be blank when a registrar is VAT-registered in the same country as registry
diff --git a/config/locales/registrars.et.yml b/config/locales/registrars.et.yml
new file mode 100644
index 000000000..1001638c1
--- /dev/null
+++ b/config/locales/registrars.et.yml
@@ -0,0 +1,5 @@
+et:
+ registrar:
+ invoice_yearly_product_description: '%{tld} registreerimine: %{length} aasta(t)'
+ invoice_monthly_product_description: '%{tld} registreerimine: %{length} kuu(d)'
+ monthly_summary_title: 'Domeenide registreerimine - %{date}'
diff --git a/config/puma.rb b/config/puma.rb
index c7f311f81..1e19380dc 100644
--- a/config/puma.rb
+++ b/config/puma.rb
@@ -1,13 +1,13 @@
# Puma can serve each request in a thread from an internal thread pool.
-# The `threads` method setting takes two numbers a minimum and maximum.
+# The `threads` method setting takes two numbers: a minimum and maximum.
# Any libraries that use thread pools should be configured to match
# the maximum value specified for Puma. Default is set to 5 threads for minimum
-# and maximum, this matches the default thread size of Active Record.
+# and maximum; this matches the default thread size of Active Record.
#
-threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
+threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads threads_count, threads_count
-# Specifies the `port` that Puma will listen on to receive requests, default is 3000.
+# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
port ENV.fetch("PORT") { 3000 }
@@ -32,16 +32,25 @@ environment ENV.fetch("RAILS_ENV") { "development" }
#
# preload_app!
+# If you are preloading your application and using Active Record, it's
+# recommended that you close any connections to the database before workers
+# are forked to prevent connection leakage.
+#
+# before_fork do
+# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord)
+# end
+
# The code in the `on_worker_boot` will be called if you are using
# clustered mode by specifying a number of `workers`. After each worker
-# process is booted this block will be run, if you are using `preload_app!`
-# option you will want to use this block to reconnect to any threads
-# or connections that may have been created at application boot, Ruby
+# process is booted, this block will be run. If you are using the `preload_app!`
+# option, you will want to use this block to reconnect to any threads
+# or connections that may have been created at application boot, as Ruby
# cannot share connections between processes.
#
# on_worker_boot do
# ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
# end
+#
# Allow puma to be restarted by `rails restart` command.
plugin :tmp_restart
diff --git a/config/routes.rb b/config/routes.rb
index 135fe8eb0..53d78dfa9 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -99,6 +99,7 @@ Rails.application.routes.draw do
get 'check'
get 'delete'
get 'search_contacts'
+ get 'remove_hold'
end
end
resources :domain_transfers, only: %i[new create]
@@ -127,11 +128,11 @@ Rails.application.routes.draw do
end
end
- get 'pay/return/:bank' => 'payments#back', as: 'return_payment_with'
- post 'pay/return/:bank' => 'payments#back'
- put 'pay/return/:bank' => 'payments#back'
- post 'pay/callback/:bank' => 'payments#callback', as: 'response_payment_with'
- get 'pay/go/:bank' => 'payments#pay', as: 'payment_with'
+ get 'pay/return/:payment_order' => 'payments#back', as: 'return_payment_with'
+ post 'pay/return/:payment_order' => 'payments#back'
+ put 'pay/return/:payment_order' => 'payments#back'
+ post 'pay/callback/:payment_order' => 'payments#callback', as: 'response_payment_with'
+ get 'pay/go/:bank' => 'payments#pay', as: 'payment_with'
namespace :settings do
resource :balance_auto_reload, controller: :balance_auto_reload, only: %i[edit update destroy]
diff --git a/config/spring.rb b/config/spring.rb
new file mode 100644
index 000000000..c9119b40c
--- /dev/null
+++ b/config/spring.rb
@@ -0,0 +1,6 @@
+%w(
+ .ruby-version
+ .rbenv-vars
+ tmp/restart.txt
+ tmp/caching-dev.txt
+).each { |path| Spring.watch(path) }
diff --git a/config/storage.yml b/config/storage.yml
new file mode 100644
index 000000000..d32f76e8f
--- /dev/null
+++ b/config/storage.yml
@@ -0,0 +1,34 @@
+test:
+ service: Disk
+ root: <%= Rails.root.join("tmp/storage") %>
+
+local:
+ service: Disk
+ root: <%= Rails.root.join("storage") %>
+
+# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
+# amazon:
+# service: S3
+# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
+# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
+# region: us-east-1
+# bucket: your_own_bucket
+
+# Remember not to checkin your GCS keyfile to a repository
+# google:
+# service: GCS
+# project: your_project
+# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
+# bucket: your_own_bucket
+
+# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
+# microsoft:
+# service: AzureStorage
+# storage_account_name: your_account_name
+# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
+# container: your_container_name
+
+# mirror:
+# service: Mirror
+# primary: local
+# mirrors: [ amazon, google, microsoft ]
diff --git a/db/data/20150601083516_add_cert_common_name.rb b/db/data/20150601083516_add_cert_common_name.rb
index ef401b871..d0959e5b7 100644
--- a/db/data/20150601083516_add_cert_common_name.rb
+++ b/db/data/20150601083516_add_cert_common_name.rb
@@ -1,16 +1,15 @@
-class AddCertCommonName < ActiveRecord::Migration
+class AddCertCommonName < ActiveRecord::Migration[5.1]
def self.up
- Certificate.all.each do |x|
- if x.crt.blank? && x.csr.present?
- pc = x.parsed_csr.try(:subject).try(:to_s) || ''
- cn = pc.scan(/\/CN=(.+)/).flatten.first
- x.common_name = cn.split('/').first
- end
- x.save
- end
+ # Certificate.all.each do |x|
+ # if x.crt.blank? && x.csr.present?
+ # pc = x.parsed_csr.try(:subject).try(:to_s) || ''
+ # cn = pc.scan(/\/CN=(.+)/).flatten.first
+ # x.common_name = cn.split('/').first
+ # end
+ # x.save
+ # end
end
def self.down
- raise ActiveRecord::IrreversibleMigration
end
end
diff --git a/db/data/20150601083800_add_cert_md5.rb b/db/data/20150601083800_add_cert_md5.rb
index 5efe4e596..4db005177 100644
--- a/db/data/20150601083800_add_cert_md5.rb
+++ b/db/data/20150601083800_add_cert_md5.rb
@@ -1,28 +1,27 @@
-class AddCertMd5 < ActiveRecord::Migration
+class AddCertMd5 < ActiveRecord::Migration[5.1]
def self.up
- Certificate.all.each do |x|
- if x.crt.present? && x.csr.present?
- x.interface = Certificate::REGISTRAR
- x.md5 = OpenSSL::Digest::MD5.new(x.parsed_crt.to_der).to_s
-
- pc = x.parsed_crt.try(:subject).try(:to_s) || ''
- cn = pc.scan(/\/CN=(.+)/).flatten.first
- x.common_name = cn.split('/').first
- elsif x.crt.present? && x.csr.blank?
- x.interface = Certificate::API
- x.md5 = OpenSSL::Digest::MD5.new(x.parsed_crt.to_der).to_s
-
- pc = x.parsed_crt.try(:subject).try(:to_s) || ''
- cn = pc.scan(/\/CN=(.+)/).flatten.first
- x.common_name = cn.split('/').first
- elsif x.crt.blank? && x.csr.present?
- x.interface = Certificate::REGISTRAR
- end
- x.save
- end
+ # Certificate.all.each do |x|
+ # if x.crt.present? && x.csr.present?
+ # x.interface = Certificate::REGISTRAR
+ # x.md5 = OpenSSL::Digest::MD5.new(x.parsed_crt.to_der).to_s
+ #
+ # pc = x.parsed_crt.try(:subject).try(:to_s) || ''
+ # cn = pc.scan(/\/CN=(.+)/).flatten.first
+ # x.common_name = cn.split('/').first
+ # elsif x.crt.present? && x.csr.blank?
+ # x.interface = Certificate::API
+ # x.md5 = OpenSSL::Digest::MD5.new(x.parsed_crt.to_der).to_s
+ #
+ # pc = x.parsed_crt.try(:subject).try(:to_s) || ''
+ # cn = pc.scan(/\/CN=(.+)/).flatten.first
+ # x.common_name = cn.split('/').first
+ # elsif x.crt.blank? && x.csr.present?
+ # x.interface = Certificate::REGISTRAR
+ # end
+ # x.save
+ # end
end
def self.down
- raise ActiveRecord::IrreversibleMigration
end
end
diff --git a/db/data/20150609093515_add_renew_setting.rb b/db/data/20150609093515_add_renew_setting.rb
index f462c38cb..2d99aa448 100644
--- a/db/data/20150609093515_add_renew_setting.rb
+++ b/db/data/20150609093515_add_renew_setting.rb
@@ -1,9 +1,8 @@
-class AddRenewSetting < ActiveRecord::Migration
+class AddRenewSetting < ActiveRecord::Migration[5.1]
def self.up
- Setting.days_to_renew_domain_before_expire = 90
+ # Setting.days_to_renew_domain_before_expire = 90
end
def self.down
- raise ActiveRecord::IrreversibleMigration
end
end
diff --git a/db/data/20150610111019_add_expire_settings.rb b/db/data/20150610111019_add_expire_settings.rb
index 9f8b9cce8..6171536dd 100644
--- a/db/data/20150610111019_add_expire_settings.rb
+++ b/db/data/20150610111019_add_expire_settings.rb
@@ -1,10 +1,9 @@
-class AddExpireSettings < ActiveRecord::Migration
+class AddExpireSettings < ActiveRecord::Migration[5.1]
def self.up
- Setting.expire_warning_period = 15
- Setting.redemption_grace_period = 30
+ # Setting.expire_warning_period = 15
+ # Setting.redemption_grace_period = 30
end
def self.down
- raise ActiveRecord::IrreversibleMigration
end
end
diff --git a/db/data/20150612125720_refactor_domain_statuses.rb b/db/data/20150612125720_refactor_domain_statuses.rb
index 00e87b4d0..de0733e3f 100644
--- a/db/data/20150612125720_refactor_domain_statuses.rb
+++ b/db/data/20150612125720_refactor_domain_statuses.rb
@@ -1,15 +1,14 @@
-class RefactorDomainStatuses < ActiveRecord::Migration
+class RefactorDomainStatuses < ActiveRecord::Migration[5.1]
def self.up
- Domain.find_each do |x|
- statuses = []
- x.domain_statuses.each do |ds|
- statuses << ds.value
- end
- x.update_column('statuses', statuses)
- end
+ # Domain.find_each do |x|
+ # statuses = []
+ # x.domain_statuses.each do |ds|
+ # statuses << ds.value
+ # end
+ # x.update_column('statuses', statuses) if x.statuses.blank?
+ # end
end
def self.down
- raise ActiveRecord::IrreversibleMigration
end
end
diff --git a/db/data/20150707103801_refactor_contact_statuses.rb b/db/data/20150707103801_refactor_contact_statuses.rb
index be6312016..e1833dd66 100644
--- a/db/data/20150707103801_refactor_contact_statuses.rb
+++ b/db/data/20150707103801_refactor_contact_statuses.rb
@@ -1,15 +1,14 @@
-class RefactorContactStatuses < ActiveRecord::Migration
+class RefactorContactStatuses < ActiveRecord::Migration[5.1]
def self.up
- Contact.find_each do |contact|
- statuses = []
- contact.depricated_statuses.each do |ds|
- statuses << ds.value
- end
- contact.update_column('statuses', statuses)
- end
+ # Contact.find_each do |contact|
+ # statuses = []
+ # contact.depricated_statuses.each do |ds|
+ # statuses << ds.value
+ # end
+ # contact.update_column('statuses', statuses)
+ # end
end
def self.down
- raise ActiveRecord::IrreversibleMigration
end
end
diff --git a/db/data/20200225085234_convert_domain_delete_date.rb b/db/data/20200225085234_convert_domain_delete_date.rb
new file mode 100644
index 000000000..81f070927
--- /dev/null
+++ b/db/data/20200225085234_convert_domain_delete_date.rb
@@ -0,0 +1,19 @@
+class ConvertDomainDeleteDate < ActiveRecord::Migration[5.1]
+ def up
+ # processed_domain_count = 0
+ #
+ # Domain.transaction do
+ # Domain.find_each do |domain|
+ # next unless domain.delete_date
+ #
+ # domain.update_columns(delete_date: domain.delete_date + 1.day)
+ # processed_domain_count += 1
+ # end
+ # end
+ #
+ # puts "Domains processed: #{processed_domain_count}"
+ end
+
+ def down
+ end
+end
diff --git a/db/data/20200225085433_delete_orphaned_registrant_verifications.rb b/db/data/20200225085433_delete_orphaned_registrant_verifications.rb
new file mode 100644
index 000000000..73c270a6a
--- /dev/null
+++ b/db/data/20200225085433_delete_orphaned_registrant_verifications.rb
@@ -0,0 +1,18 @@
+class DeleteOrphanedRegistrantVerifications < ActiveRecord::Migration[5.1]
+ def up
+ # orphaned_registrant_verifications = RegistrantVerification.where.not(domain_id: Domain.ids)
+ # orphaned_registrant_verification_count = orphaned_registrant_verifications.count
+ # processed_registrant_verification_count = 0
+ #
+ # orphaned_registrant_verifications.each do |registrant_verification|
+ # registrant_verification.destroy!
+ # processed_registrant_verification_count += 1
+ # end
+ #
+ # puts "Processed: #{processed_registrant_verification_count} out of" \
+ # " #{orphaned_registrant_verification_count}"
+ end
+
+ def down
+ end
+end
diff --git a/db/data/20200225085539_regenerate_registrar_reference_numbers.rb b/db/data/20200225085539_regenerate_registrar_reference_numbers.rb
new file mode 100644
index 000000000..fbd2a5c5f
--- /dev/null
+++ b/db/data/20200225085539_regenerate_registrar_reference_numbers.rb
@@ -0,0 +1,19 @@
+class RegenerateRegistrarReferenceNumbers < ActiveRecord::Migration[5.1]
+ def up
+ # processed_registrar_count = 0
+ #
+ # Registrar.transaction do
+ # Registrar.all.each do |registrar|
+ # next unless registrar.reference_no.start_with?('RF')
+ #
+ # registrar.update_columns(reference_no: Billing::ReferenceNo.generate)
+ # processed_registrar_count += 1
+ # end
+ # end
+ #
+ # puts "Registrars processed: #{processed_registrar_count}"
+ end
+
+ def down
+ end
+end
diff --git a/db/data_schema.rb b/db/data_schema.rb
new file mode 100644
index 000000000..f4a3f5d8a
--- /dev/null
+++ b/db/data_schema.rb
@@ -0,0 +1,2 @@
+# encoding: UTF-8
+DataMigrate::Data.define(version: 20150707103801)
diff --git a/db/migrate/20200130092113_create_payment_orders.rb b/db/migrate/20200130092113_create_payment_orders.rb
new file mode 100644
index 000000000..97d86a034
--- /dev/null
+++ b/db/migrate/20200130092113_create_payment_orders.rb
@@ -0,0 +1,15 @@
+class CreatePaymentOrders < ActiveRecord::Migration[5.0]
+ def change
+ create_table :payment_orders do |t|
+ t.string :type, null: false
+ t.string :status, default: 'issued', null: false
+ t.belongs_to :invoice, foreign_key: true
+ t.jsonb :response, null: true
+ t.string :notes, null: true
+ t.string :creator_str
+ t.string :updator_str
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20200203143458_create_payment_order_versions.rb b/db/migrate/20200203143458_create_payment_order_versions.rb
new file mode 100644
index 000000000..d02b300e1
--- /dev/null
+++ b/db/migrate/20200203143458_create_payment_order_versions.rb
@@ -0,0 +1,16 @@
+class CreatePaymentOrderVersions < ActiveRecord::Migration[5.0]
+ def change
+ create_table :log_payment_orders do |t|
+ t.string :item_type, null: false
+ t.integer :item_id, null: false
+ t.string :event, null: false
+ t.string :whodunnit
+ t.jsonb :object
+ t.jsonb :object_changes
+ t.datetime :created_at
+ t.string :session
+ t.jsonb :children
+ t.string :uuid
+ end
+ end
+end
diff --git a/db/migrate/20200204103125_add_e_invoice_sent_at_to_invoice.rb b/db/migrate/20200204103125_add_e_invoice_sent_at_to_invoice.rb
new file mode 100644
index 000000000..e0e5f2cd0
--- /dev/null
+++ b/db/migrate/20200204103125_add_e_invoice_sent_at_to_invoice.rb
@@ -0,0 +1,5 @@
+class AddEInvoiceSentAtToInvoice < ActiveRecord::Migration[5.0]
+ def change
+ add_column :invoices, :e_invoice_sent_at, :datetime
+ end
+end
diff --git a/db/migrate/20200311114649_update_zone_generation_migration.rb b/db/migrate/20200311114649_update_zone_generation_migration.rb
new file mode 100644
index 000000000..2c516474d
--- /dev/null
+++ b/db/migrate/20200311114649_update_zone_generation_migration.rb
@@ -0,0 +1,247 @@
+class UpdateZoneGenerationMigration < ActiveRecord::Migration[5.1]
+ def up
+ execute <<-SQL
+ CREATE OR REPLACE FUNCTION generate_zonefile(i_origin character varying) RETURNS text
+ LANGUAGE plpgsql
+ AS $_$
+ DECLARE
+ zone_header text := concat('$ORIGIN ', i_origin, '.');
+ serial_num varchar;
+ include_filter varchar := '';
+ exclude_filter varchar := '';
+ tmp_var text;
+ ret text;
+ BEGIN
+ -- define filters
+ include_filter = '%.' || i_origin;
+
+ -- for %.%.%
+ IF i_origin ~ '.' THEN
+ exclude_filter := '';
+ -- for %.%
+ ELSE
+ exclude_filter := '%.%.' || i_origin;
+ END IF;
+
+ SELECT ROUND(extract(epoch from now() at time zone 'utc')) INTO serial_num;
+
+ -- zonefile header
+ SELECT concat(
+ format('%-10s', '$ORIGIN .'), chr(10),
+ format('%-10s', '$TTL'), zf.ttl, chr(10), chr(10),
+ format('%-10s', i_origin || '.'), 'IN SOA ', zf.master_nameserver, '. ', zf.email, '. (', chr(10),
+ format('%-17s', ''), format('%-12s', serial_num), '; serial number', chr(10),
+ format('%-17s', ''), format('%-12s', zf.refresh), '; refresh, seconds', chr(10),
+ format('%-17s', ''), format('%-12s', zf.retry), '; retry, seconds', chr(10),
+ format('%-17s', ''), format('%-12s', zf.expire), '; expire, seconds', chr(10),
+ format('%-17s', ''), format('%-12s', zf.minimum_ttl), '; minimum TTL, seconds', chr(10),
+ format('%-17s', ''), ')'
+ ) FROM zones zf WHERE i_origin = zf.origin INTO tmp_var;
+
+ ret = concat(tmp_var, chr(10), chr(10));
+
+ -- origin ns records
+ SELECT ns_records FROM zones zf WHERE i_origin = zf.origin INTO tmp_var;
+ ret := concat(ret, '; Zone NS Records', chr(10), tmp_var, chr(10));
+
+ -- ns records
+ SELECT array_to_string(
+ array(
+ SELECT concat(d.name_puny, '. IN NS ', coalesce(ns.hostname_puny, ns.hostname), '.')
+ FROM domains d
+ JOIN nameservers ns ON ns.domain_id = d.id
+ WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter
+ AND NOT ('{serverHold,clientHold,inactive}' && d.statuses)
+ ORDER BY d.name
+ ),
+ chr(10)
+ ) INTO tmp_var;
+
+ ret := concat(ret, tmp_var, chr(10), chr(10));
+
+ -- origin a glue records
+ SELECT a_records FROM zones zf WHERE i_origin = zf.origin INTO tmp_var;
+ ret := concat(ret, '; Zone A Records', chr(10), tmp_var, chr(10));
+
+ -- a glue records for other nameservers
+ SELECT array_to_string(
+ array(
+ SELECT concat(coalesce(ns.hostname_puny, ns.hostname), '. IN A ', unnest(ns.ipv4))
+ FROM nameservers ns
+ JOIN domains d ON d.id = ns.domain_id
+ WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter
+ AND (ns.hostname LIKE '%.' || d.name) OR (ns.hostname LIKE d.name)
+ AND d.name <> i_origin
+ AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> '{}'
+ AND NOT ('{serverHold,clientHold,inactive}' && d.statuses)
+ ), chr(10)
+ ) INTO tmp_var;
+
+ ret := concat(ret, tmp_var, chr(10), chr(10));
+
+ -- origin aaaa glue records
+ SELECT a4_records FROM zones zf WHERE i_origin = zf.origin INTO tmp_var;
+ ret := concat(ret, '; Zone AAAA Records', chr(10), tmp_var, chr(10));
+
+ -- aaaa glue records for other nameservers
+ SELECT array_to_string(
+ array(
+ SELECT concat(coalesce(ns.hostname_puny, ns.hostname), '. IN AAAA ', unnest(ns.ipv6))
+ FROM nameservers ns
+ JOIN domains d ON d.id = ns.domain_id
+ WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter
+ AND (ns.hostname LIKE '%.' || d.name) OR (ns.hostname LIKE d.name)
+ AND d.name <> i_origin
+ AND ns.ipv6 IS NOT NULL AND ns.ipv6 <> '{}'
+ AND NOT ('{serverHold,clientHold,inactive}' && d.statuses)
+ ), chr(10)
+ ) INTO tmp_var;
+
+ ret := concat(ret, tmp_var, chr(10), chr(10));
+
+ -- ds records
+ SELECT array_to_string(
+ array(
+ SELECT concat(
+ d.name_puny, '. 3600 IN DS ', dk.ds_key_tag, ' ',
+ dk.ds_alg, ' ', dk.ds_digest_type, ' ', dk.ds_digest
+ )
+ FROM domains d
+ JOIN dnskeys dk ON dk.domain_id = d.id
+ WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter AND dk.flags = 257
+ AND NOT ('{serverHold,clientHold,inactive}' && d.statuses)
+ ),
+ chr(10)
+ ) INTO tmp_var;
+
+ ret := concat(ret, '; Zone DS Records', chr(10), tmp_var, chr(10));
+
+ RETURN ret;
+ END;
+ $_$;
+ SQL
+ end
+
+ def down
+ execute <<-SQL
+ CREATE OR REPLACE FUNCTION generate_zonefile(i_origin character varying) RETURNS text
+ LANGUAGE plpgsql
+ AS $_$
+ DECLARE
+ zone_header text := concat('$ORIGIN ', i_origin, '.');
+ serial_num varchar;
+ include_filter varchar := '';
+ exclude_filter varchar := '';
+ tmp_var text;
+ ret text;
+ BEGIN
+ -- define filters
+ include_filter = '%.' || i_origin;
+
+ -- for %.%.%
+ IF i_origin ~ '.' THEN
+ exclude_filter := '';
+ -- for %.%
+ ELSE
+ exclude_filter := '%.%.' || i_origin;
+ END IF;
+
+ SELECT ROUND(extract(epoch from now() at time zone 'utc')) INTO serial_num;
+
+ -- zonefile header
+ SELECT concat(
+ format('%-10s', '$ORIGIN .'), chr(10),
+ format('%-10s', '$TTL'), zf.ttl, chr(10), chr(10),
+ format('%-10s', i_origin || '.'), 'IN SOA ', zf.master_nameserver, '. ', zf.email, '. (', chr(10),
+ format('%-17s', ''), format('%-12s', serial_num), '; serial number', chr(10),
+ format('%-17s', ''), format('%-12s', zf.refresh), '; refresh, seconds', chr(10),
+ format('%-17s', ''), format('%-12s', zf.retry), '; retry, seconds', chr(10),
+ format('%-17s', ''), format('%-12s', zf.expire), '; expire, seconds', chr(10),
+ format('%-17s', ''), format('%-12s', zf.minimum_ttl), '; minimum TTL, seconds', chr(10),
+ format('%-17s', ''), ')'
+ ) FROM zones zf WHERE i_origin = zf.origin INTO tmp_var;
+
+ ret = concat(tmp_var, chr(10), chr(10));
+
+ -- origin ns records
+ SELECT ns_records FROM zones zf WHERE i_origin = zf.origin INTO tmp_var;
+ ret := concat(ret, '; Zone NS Records', chr(10), tmp_var, chr(10));
+
+ -- ns records
+ SELECT array_to_string(
+ array(
+ SELECT concat(d.name_puny, '. IN NS ', coalesce(ns.hostname_puny, ns.hostname), '.')
+ FROM domains d
+ JOIN nameservers ns ON ns.domain_id = d.id
+ WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter
+ AND NOT ('{serverHold,clientHold,inactive}' && d.statuses)
+ ORDER BY d.name
+ ),
+ chr(10)
+ ) INTO tmp_var;
+
+ ret := concat(ret, tmp_var, chr(10), chr(10));
+
+ -- origin a glue records
+ SELECT a_records FROM zones zf WHERE i_origin = zf.origin INTO tmp_var;
+ ret := concat(ret, '; Zone A Records', chr(10), tmp_var, chr(10));
+
+ -- a glue records for other nameservers
+ SELECT array_to_string(
+ array(
+ SELECT concat(coalesce(ns.hostname_puny, ns.hostname), '. IN A ', unnest(ns.ipv4))
+ FROM nameservers ns
+ JOIN domains d ON d.id = ns.domain_id
+ WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter
+ AND ns.hostname LIKE '%.' || d.name
+ AND d.name <> i_origin
+ AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> '{}'
+ AND NOT ('{serverHold,clientHold,inactive}' && d.statuses)
+ ), chr(10)
+ ) INTO tmp_var;
+
+ ret := concat(ret, tmp_var, chr(10), chr(10));
+
+ -- origin aaaa glue records
+ SELECT a4_records FROM zones zf WHERE i_origin = zf.origin INTO tmp_var;
+ ret := concat(ret, '; Zone AAAA Records', chr(10), tmp_var, chr(10));
+
+ -- aaaa glue records for other nameservers
+ SELECT array_to_string(
+ array(
+ SELECT concat(coalesce(ns.hostname_puny, ns.hostname), '. IN AAAA ', unnest(ns.ipv6))
+ FROM nameservers ns
+ JOIN domains d ON d.id = ns.domain_id
+ WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter
+ AND ns.hostname LIKE '%.' || d.name
+ AND d.name <> i_origin
+ AND ns.ipv6 IS NOT NULL AND ns.ipv6 <> '{}'
+ AND NOT ('{serverHold,clientHold,inactive}' && d.statuses)
+ ), chr(10)
+ ) INTO tmp_var;
+
+ ret := concat(ret, tmp_var, chr(10), chr(10));
+
+ -- ds records
+ SELECT array_to_string(
+ array(
+ SELECT concat(
+ d.name_puny, '. 3600 IN DS ', dk.ds_key_tag, ' ',
+ dk.ds_alg, ' ', dk.ds_digest_type, ' ', dk.ds_digest
+ )
+ FROM domains d
+ JOIN dnskeys dk ON dk.domain_id = d.id
+ WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter AND dk.flags = 257
+ AND NOT ('{serverHold,clientHold,inactive}' && d.statuses)
+ ),
+ chr(10)
+ ) INTO tmp_var;
+
+ ret := concat(ret, '; Zone DS Records', chr(10), tmp_var, chr(10));
+
+ RETURN ret;
+ END;
+ $_$;
+ SQL
+ end
+end
diff --git a/db/structure.sql b/db/structure.sql
index a23623bae..604238d4c 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -140,7 +140,7 @@ CREATE FUNCTION public.generate_zonefile(i_origin character varying) RETURNS tex
FROM nameservers ns
JOIN domains d ON d.id = ns.domain_id
WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter
- AND ns.hostname LIKE '%.' || d.name
+ AND (ns.hostname LIKE '%.' || d.name) OR (ns.hostname LIKE d.name)
AND d.name <> i_origin
AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> '{}'
AND NOT ('{serverHold,clientHold,inactive}' && d.statuses)
@@ -160,7 +160,7 @@ CREATE FUNCTION public.generate_zonefile(i_origin character varying) RETURNS tex
FROM nameservers ns
JOIN domains d ON d.id = ns.domain_id
WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter
- AND ns.hostname LIKE '%.' || d.name
+ AND (ns.hostname LIKE '%.' || d.name) OR (ns.hostname LIKE d.name)
AND d.name <> i_origin
AND ns.ipv6 IS NOT NULL AND ns.ipv6 <> '{}'
AND NOT ('{serverHold,clientHold,inactive}' && d.statuses)
@@ -746,7 +746,6 @@ CREATE TABLE public.domains (
locked_by_registrant_at timestamp without time zone,
force_delete_start timestamp without time zone,
force_delete_data public.hstore
-
);
@@ -886,6 +885,7 @@ CREATE TABLE public.invoices (
in_directo boolean DEFAULT false,
buyer_vat_no character varying,
issue_date date NOT NULL,
+ e_invoice_sent_at timestamp without time zone,
CONSTRAINT invoices_due_date_is_not_before_issue_date CHECK ((due_date >= issue_date))
);
@@ -1515,6 +1515,44 @@ CREATE SEQUENCE public.log_notifications_id_seq
ALTER SEQUENCE public.log_notifications_id_seq OWNED BY public.log_notifications.id;
+--
+-- Name: log_payment_orders; Type: TABLE; Schema: public; Owner: -; Tablespace:
+--
+
+CREATE TABLE public.log_payment_orders (
+ id integer NOT NULL,
+ item_type character varying NOT NULL,
+ item_id integer NOT NULL,
+ event character varying NOT NULL,
+ whodunnit character varying,
+ object jsonb,
+ object_changes jsonb,
+ created_at timestamp without time zone,
+ session character varying,
+ children jsonb,
+ uuid character varying
+);
+
+
+--
+-- Name: log_payment_orders_id_seq; Type: SEQUENCE; Schema: public; Owner: -
+--
+
+CREATE SEQUENCE public.log_payment_orders_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+--
+-- Name: log_payment_orders_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
+--
+
+ALTER SEQUENCE public.log_payment_orders_id_seq OWNED BY public.log_payment_orders.id;
+
+
--
-- Name: log_registrant_verifications; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
@@ -1818,6 +1856,43 @@ CREATE SEQUENCE public.notifications_id_seq
ALTER SEQUENCE public.notifications_id_seq OWNED BY public.notifications.id;
+--
+-- Name: payment_orders; Type: TABLE; Schema: public; Owner: -; Tablespace:
+--
+
+CREATE TABLE public.payment_orders (
+ id integer NOT NULL,
+ type character varying NOT NULL,
+ status character varying DEFAULT 'issued'::character varying NOT NULL,
+ invoice_id integer,
+ response jsonb,
+ notes character varying,
+ creator_str character varying,
+ updator_str character varying,
+ created_at timestamp without time zone NOT NULL,
+ updated_at timestamp without time zone NOT NULL
+);
+
+
+--
+-- Name: payment_orders_id_seq; Type: SEQUENCE; Schema: public; Owner: -
+--
+
+CREATE SEQUENCE public.payment_orders_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+--
+-- Name: payment_orders_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
+--
+
+ALTER SEQUENCE public.payment_orders_id_seq OWNED BY public.payment_orders.id;
+
+
--
-- Name: prices; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
@@ -2499,6 +2574,13 @@ ALTER TABLE ONLY public.log_nameservers ALTER COLUMN id SET DEFAULT nextval('pub
ALTER TABLE ONLY public.log_notifications ALTER COLUMN id SET DEFAULT nextval('public.log_notifications_id_seq'::regclass);
+--
+-- Name: id; Type: DEFAULT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.log_payment_orders ALTER COLUMN id SET DEFAULT nextval('public.log_payment_orders_id_seq'::regclass);
+
+
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
--
@@ -2555,6 +2637,13 @@ ALTER TABLE ONLY public.nameservers ALTER COLUMN id SET DEFAULT nextval('public.
ALTER TABLE ONLY public.notifications ALTER COLUMN id SET DEFAULT nextval('public.notifications_id_seq'::regclass);
+--
+-- Name: id; Type: DEFAULT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.payment_orders ALTER COLUMN id SET DEFAULT nextval('public.payment_orders_id_seq'::regclass);
+
+
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
--
@@ -2904,6 +2993,14 @@ ALTER TABLE ONLY public.log_notifications
ADD CONSTRAINT log_notifications_pkey PRIMARY KEY (id);
+--
+-- Name: log_payment_orders_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
+--
+
+ALTER TABLE ONLY public.log_payment_orders
+ ADD CONSTRAINT log_payment_orders_pkey PRIMARY KEY (id);
+
+
--
-- Name: log_registrant_verifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
@@ -2968,6 +3065,14 @@ ALTER TABLE ONLY public.notifications
ADD CONSTRAINT notifications_pkey PRIMARY KEY (id);
+--
+-- Name: payment_orders_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
+--
+
+ALTER TABLE ONLY public.payment_orders
+ ADD CONSTRAINT payment_orders_pkey PRIMARY KEY (id);
+
+
--
-- Name: prices_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
@@ -3629,6 +3734,13 @@ CREATE INDEX index_nameservers_on_domain_id ON public.nameservers USING btree (d
CREATE INDEX index_notifications_on_registrar_id ON public.notifications USING btree (registrar_id);
+--
+-- Name: index_payment_orders_on_invoice_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
+--
+
+CREATE INDEX index_payment_orders_on_invoice_id ON public.payment_orders USING btree (invoice_id);
+
+
--
-- Name: index_prices_on_zone_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
--
@@ -3895,6 +4007,14 @@ ALTER TABLE ONLY public.registrant_verifications
ADD CONSTRAINT fk_rails_f41617a0e9 FOREIGN KEY (domain_id) REFERENCES public.domains(id);
+--
+-- Name: fk_rails_f9dc5857c3; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.payment_orders
+ ADD CONSTRAINT fk_rails_f9dc5857c3 FOREIGN KEY (invoice_id) REFERENCES public.invoices(id);
+
+
--
-- Name: invoice_items_invoice_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@@ -4339,6 +4459,9 @@ INSERT INTO "schema_migrations" (version) VALUES
('20191212133136'),
('20191227110904'),
('20200113091254'),
-('20200115102202');
-
+('20200115102202'),
+('20200130092113'),
+('20200203143458'),
+('20200204103125'),
+('20200311114649');
diff --git a/lib/tasks/data_migrations/.keep b/lib/tasks/data_migrations/.keep
new file mode 100644
index 000000000..e69de29bb
diff --git a/lib/tasks/data_migrations/convert_domain_delete_date.rake b/lib/tasks/data_migrations/convert_domain_delete_date.rake
deleted file mode 100644
index 7eeee5cf0..000000000
--- a/lib/tasks/data_migrations/convert_domain_delete_date.rake
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace :data_migrations do
- task convert_domain_delete_date: :environment do
- processed_domain_count = 0
-
- Domain.transaction do
- Domain.find_each do |domain|
- next unless domain.delete_date
-
- domain.update_columns(delete_date: domain.delete_date + 1.day)
- processed_domain_count += 1
- end
- end
-
- puts "Domains processed: #{processed_domain_count}"
- end
-end
\ No newline at end of file
diff --git a/lib/tasks/data_migrations/delete_orphaned_registrant_verifications.rake b/lib/tasks/data_migrations/delete_orphaned_registrant_verifications.rake
deleted file mode 100644
index f65db547e..000000000
--- a/lib/tasks/data_migrations/delete_orphaned_registrant_verifications.rake
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace :data_migrations do
- task delete_orphaned_registrant_verifications: :environment do
- orphaned_registrant_verifications = RegistrantVerification.where.not(domain_id: Domain.ids)
- orphaned_registrant_verification_count = orphaned_registrant_verifications.count
- processed_registrant_verification_count = 0
-
- orphaned_registrant_verifications.each do |registrant_verification|
- registrant_verification.destroy!
- processed_registrant_verification_count += 1
- end
-
- puts "Processed: #{processed_registrant_verification_count} out of" \
- " #{orphaned_registrant_verification_count}"
- end
-end
diff --git a/lib/tasks/data_migrations/regenerate_registrar_reference_numbers.rake b/lib/tasks/data_migrations/regenerate_registrar_reference_numbers.rake
deleted file mode 100644
index 6f6aaebe2..000000000
--- a/lib/tasks/data_migrations/regenerate_registrar_reference_numbers.rake
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace :data_migrations do
- task regenerate_registrar_reference_numbers: [:environment] do
- processed_registrar_count = 0
-
- Registrar.transaction do
- Registrar.all.each do |registrar|
- next unless registrar.reference_no.start_with?('RF')
-
- registrar.update_columns(reference_no: Billing::ReferenceNo.generate)
- processed_registrar_count += 1
- end
- end
-
- puts "Registrars processed: #{processed_registrar_count}"
- end
-end
diff --git a/test/fixtures/account_activities.yml b/test/fixtures/account_activities.yml
index dbe1dc2aa..8f883e424 100644
--- a/test/fixtures/account_activities.yml
+++ b/test/fixtures/account_activities.yml
@@ -2,4 +2,4 @@ one:
account: cash
invoice: one
bank_transaction: one
- created_at: <%= Time.zone.parse('2010-07-05 10:00') %>
\ No newline at end of file
+ created_at: <%= Time.zone.parse('2010-07-05 10:00') %>
diff --git a/test/fixtures/files/bank_statement_test.txt b/test/fixtures/files/bank_statement_test.txt
new file mode 100644
index 000000000..d3f561a7d
--- /dev/null
+++ b/test/fixtures/files/bank_statement_test.txt
@@ -0,0 +1,7 @@
+VV 000689NL85RABO74981124931508051533
+VV 220150805 M NL85RABO7498112493EUR Algsaldo C 26397
+VV 12015080520890321MK NL85RABO7498112493EUR401NL93ABNA8027105943 Registrar Second Prepayment Invoice no.3131071 C 72055
+VV 12015080520890321MK NL85RABO7498112493EUR401NL93ABNA8027105943 eedirect Prepayment Invoice no. 13 C 480
+VV 12015080521042372MK NL85RABO7498112493EUR767EE021222121767323770 Line Suva 8 Arve nr 2015-01 D 55000
+VV 320150805 M NL85RABO7498112493EUR Lõppsaldo C 5417
+VV 999 176980
diff --git a/test/fixtures/invoice_items.yml b/test/fixtures/invoice_items.yml
index 19409df81..a61ef4eb0 100644
--- a/test/fixtures/invoice_items.yml
+++ b/test/fixtures/invoice_items.yml
@@ -4,3 +4,10 @@ one:
quantity: 1
unit: pc
invoice: one
+
+two:
+ description: Acme services
+ price: 5
+ quantity: 1
+ unit: pc
+ invoice: unpaid
diff --git a/test/fixtures/invoices.yml b/test/fixtures/invoices.yml
index bc9fa2900..6c0dca021 100644
--- a/test/fixtures/invoices.yml
+++ b/test/fixtures/invoices.yml
@@ -24,3 +24,30 @@ one:
reference_no: 13
number: 1
description: Order nr 1 from registrar 1234567 second number 2345678
+
+unpaid:
+ issue_date: <%= Date.parse '2010-07-05' %>
+ due_date: <%= Date.parse '2010-07-06' %>
+ currency: EUR
+ seller_name: Seller Ltd
+ seller_reg_no: 1234
+ seller_iban: US75512108001245126199
+ seller_bank: Main Bank
+ seller_swift: swift
+ seller_email: info@seller.test
+ seller_country_code: US
+ seller_street: Main Street 1
+ seller_city: New York
+ seller_contact_name: John Doe
+ buyer: bestnames
+ buyer_name: Buyer Ltd
+ buyer_reg_no: 12345
+ buyer_email: info@buyer.test
+ buyer_country_code: GB
+ buyer_street: Main Street 2
+ buyer_city: London
+ vat_rate: 0.1
+ total: 16.50
+ reference_no: 13
+ number: 2
+ description: Order nr 2 from registrar 1234567 second number 2345678
diff --git a/test/fixtures/payment_orders.yml b/test/fixtures/payment_orders.yml
new file mode 100644
index 000000000..39289b7d1
--- /dev/null
+++ b/test/fixtures/payment_orders.yml
@@ -0,0 +1,27 @@
+everypay_issued:
+ type: PaymentOrders::EveryPay
+ status: issued
+ invoice: one
+ response:
+ notes:
+
+banklink_issued:
+ type: PaymentOrders::Seb
+ status: issued
+ invoice: one
+ response:
+ notes:
+
+paid:
+ type: PaymentOrders::EveryPay
+ status: paid
+ invoice: unpaid
+ response: "{}"
+ notes:
+
+cancelled:
+ type: PaymentOrders::Seb
+ status: cancelled
+ invoice: unpaid
+ response: "{}"
+ notes: User failed to make payment. Bank responded with code 1911
diff --git a/test/integration/contact/audit_log_test.rb b/test/integration/contact/audit_log_test.rb
index f0f6a4bf2..41699d595 100644
--- a/test/integration/contact/audit_log_test.rb
+++ b/test/integration/contact/audit_log_test.rb
@@ -5,7 +5,7 @@ class ContactAuditLogTest < ActionDispatch::IntegrationTest
contact = contacts(:john)
contact.legal_document_id = 1
- assert_difference 'contact.versions.count' do
+ assert_difference 'contact.versions.count', 1 do
contact.save!
end
@@ -13,4 +13,4 @@ class ContactAuditLogTest < ActionDispatch::IntegrationTest
assert_equal ({ legal_documents: [1] }).with_indifferent_access,
contact_version.children.with_indifferent_access
end
-end
\ No newline at end of file
+end
diff --git a/test/integration/domain/audit_log_test.rb b/test/integration/domain/audit_log_test.rb
index 292994ca3..a17fded0d 100644
--- a/test/integration/domain/audit_log_test.rb
+++ b/test/integration/domain/audit_log_test.rb
@@ -14,7 +14,7 @@ class DomainAuditLogTest < ActionDispatch::IntegrationTest
assert_equal registrant_id, domain.registrant_id
domain.legal_document_id = legal_document_id
- assert_difference 'domain.versions.count' do
+ assert_difference 'domain.versions.count', 1 do
domain.save!
end
@@ -26,4 +26,4 @@ class DomainAuditLogTest < ActionDispatch::IntegrationTest
assert_equal [legal_document_id], domain_version.children['legal_documents']
assert_equal [registrant_id], domain_version.children['registrant']
end
-end
\ No newline at end of file
+end
diff --git a/test/integration/registrar_area/invoices/payment_callback_test.rb b/test/integration/registrar_area/invoices/payment_callback_test.rb
index 23db55e84..94ca6e373 100644
--- a/test/integration/registrar_area/invoices/payment_callback_test.rb
+++ b/test/integration/registrar_area/invoices/payment_callback_test.rb
@@ -6,34 +6,40 @@ class PaymentCallbackTest < ApplicationIntegrationTest
@user = users(:api_bestnames)
sign_in @user
+
+ @payment_order = payment_orders(:everypay_issued)
+ @invoice = invoices(:one)
+ @invoice.update!(account_activity: nil, total: 12)
end
def test_every_pay_callback_returns_status_200
- invoice = payable_invoice
- assert_matching_bank_transaction_exists(invoice)
-
- request_params = every_pay_request_params.merge(invoice_id: invoice.id)
- post "/registrar/pay/callback/every_pay", params: request_params
+ request_params = every_pay_request_params
+ post "/registrar/pay/callback/#{@payment_order.id}", params: request_params
assert_response :ok
end
+ def test_invoice_is_marked_as_paid
+ request_params = every_pay_request_params
+ post "/registrar/pay/callback/#{@payment_order.id}", params: request_params
+
+ assert @payment_order.invoice.paid?
+ end
+
+ def failure_log_is_created_if_unsuccessful_payment
+ request_params = every_pay_request_params.dup
+ request_params['payment_state'] = 'cancelled'
+ request_params['transaction_result'] = 'failed'
+
+ post "/registrar/pay/callback/#{@payment_order.id}", params: request_params
+
+ @payment_order.reload
+ assert @payment_order.cancelled?
+ assert_includes @payment_order.notes, 'Payment state: cancelled'
+ end
+
private
- def payable_invoice
- invoice = invoices(:one)
- invoice.update!(account_activity: nil)
- invoice
- end
-
- def assert_matching_bank_transaction_exists(invoice)
- assert BankTransaction.find_by(
- description: invoice.description,
- currency: invoice.currency,
- iban: invoice.seller_iban
- ), 'Matching bank transaction should exist'
- end
-
def every_pay_request_params
{
nonce: "392f2d7748bc8cb0d14f263ebb7b8932",
diff --git a/test/integration/registrar_area/invoices/payment_return_test.rb b/test/integration/registrar_area/invoices/payment_return_test.rb
index de65cccb0..a4adb8160 100644
--- a/test/integration/registrar_area/invoices/payment_return_test.rb
+++ b/test/integration/registrar_area/invoices/payment_return_test.rb
@@ -8,6 +8,9 @@ class PaymentReturnTest < ApplicationIntegrationTest
sign_in @user
@invoice = invoices(:one)
+ @invoice.update!(account_activity: nil, total: 12)
+ @everypay_order = payment_orders(:everypay_issued)
+ @banklink_order = payment_orders(:banklink_issued)
end
def every_pay_request_params
@@ -57,33 +60,78 @@ class PaymentReturnTest < ApplicationIntegrationTest
}
end
- def test_every_pay_return_creates_activity_redirects_to_invoice_path
- request_params = every_pay_request_params.merge(invoice_id: @invoice.id)
+ def test_successful_bank_payment_marks_invoice_as_paid
+ @invoice.update!(account_activity: nil)
+ request_params = bank_link_request_params
- post "/registrar/pay/return/every_pay", params: request_params
+ post "/registrar/pay/return/#{@banklink_order.id}", params: request_params
+
+ @banklink_order.reload
+ assert @banklink_order.invoice.paid?
+ end
+
+ def test_every_pay_return_creates_activity_redirects_to_invoice_path
+ request_params = every_pay_request_params
+
+ post "/registrar/pay/return/#{@everypay_order.id}", params: request_params
assert_equal(302, response.status)
assert_redirected_to(registrar_invoice_path(@invoice))
end
- def test_Every_Pay_return_raises_RecordNotFound
- request_params = every_pay_request_params.merge(invoice_id: "178907")
+ def test_every_pay_return_raises_record_not_found
+ request_params = every_pay_request_params
assert_raises(ActiveRecord::RecordNotFound) do
- post "/registrar/pay/return/every_pay", params: request_params
+ post '/registrar/pay/return/123456', params: request_params
end
end
def test_bank_link_return_redirects_to_invoice_paths
- request_params = bank_link_request_params.merge(invoice_id: @invoice.id)
+ request_params = bank_link_request_params
- post "/registrar/pay/return/seb", params: request_params
+ post "/registrar/pay/return/#{@banklink_order.id}", params: request_params
assert_equal(302, response.status)
assert_redirected_to(registrar_invoice_path(@invoice))
end
def test_bank_link_return
- request_params = bank_link_request_params.merge(invoice_id: "178907")
+ request_params = bank_link_request_params
assert_raises(ActiveRecord::RecordNotFound) do
- post "/registrar/pay/return/seb", params: request_params
+ post '/registrar/pay/return/123456', params: request_params
end
end
+
+ def test_marks_as_paid_and_adds_notes_if_failed_to_bind
+ request_params = bank_link_request_params
+
+ post "/registrar/pay/return/#{@banklink_order.id}", params: request_params
+ post "/registrar/pay/return/#{@banklink_order.id}", params: request_params
+ @banklink_order.reload
+
+ assert @banklink_order.notes.present?
+ assert @banklink_order.paid?
+ assert_includes @banklink_order.notes, 'Failed to bind'
+ end
+
+ def test_failed_bank_link_payment_creates_brief_error_explanation
+ request_params = bank_link_request_params.dup
+ request_params['VK_SERVICE'] = '1911'
+
+ post "/registrar/pay/return/#{@banklink_order.id}", params: request_params
+
+ @banklink_order.reload
+
+ assert_includes @banklink_order.notes, 'Bank responded with code 1911'
+ end
+
+ def test_failed_every_pay_payment_creates_brief_error_explanation
+ request_params = every_pay_request_params.dup
+ request_params['payment_state'] = 'cancelled'
+ request_params['transaction_result'] = 'failed'
+
+ post "/registrar/pay/return/#{@everypay_order.id}", params: request_params
+
+ @everypay_order.reload
+
+ assert_includes @everypay_order.notes, 'Payment state: cancelled'
+ end
end
diff --git a/test/integration/tasks/data_migrations/regenerate_registrar_reference_numbers_test.rb b/test/integration/tasks/data_migrations/regenerate_registrar_reference_numbers_test.rb
deleted file mode 100644
index 946c6b898..000000000
--- a/test/integration/tasks/data_migrations/regenerate_registrar_reference_numbers_test.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-require 'test_helper'
-
-class RegenerateRegistrarReferenceNumbersTaskTest < ActiveSupport::TestCase
- def test_regenerates_registrar_reference_numbers_to_estonian_format
- registrar = registrars(:bestnames)
- registrar.update_column(:reference_no, 'RF1111')
-
- capture_io { run_task }
- registrar.reload
-
- assert_not registrar.reference_no.start_with?('RF')
- end
-
- def test_bypasses_registrar_validation
- registrar = registrars(:invalid)
- registrar.update_column(:reference_no, 'RF1111')
- assert registrar.invalid?
-
- capture_io { run_task }
- registrar.reload
-
- assert_not registrar.reference_no.start_with?('RF')
- end
-
- def test_does_not_regenerate_when_the_task_is_run_again
- registrar = registrars(:bestnames)
- registrar.update!(reference_no: '1111')
-
- capture_io { run_task }
- registrar.reload
-
- assert_equal '1111', registrar.reference_no
- end
-
- def test_keeps_iso_reference_number_on_the_invoice_unchanged
- registrar = registrars(:bestnames)
- registrar.update_column(:reference_no, 'RF1111')
- invoice = invoices(:one)
- invoice.update!(reference_no: 'RF2222')
-
- capture_io { run_task }
- invoice.reload
-
- assert_equal 'RF2222', invoice.reference_no
- end
-
- def test_output
- registrar = registrars(:bestnames)
- registrar.update_column(:reference_no, 'RF1111')
-
- assert_output "Registrars processed: 1\n" do
- run_task
- end
- end
-
- private
-
- def run_task
- Rake::Task['data_migrations:regenerate_registrar_reference_numbers'].execute
- end
-end
diff --git a/test/jobs/directo_invoice_forward_job_test.rb b/test/jobs/directo_invoice_forward_job_test.rb
new file mode 100644
index 000000000..8a4fb43aa
--- /dev/null
+++ b/test/jobs/directo_invoice_forward_job_test.rb
@@ -0,0 +1,146 @@
+require "test_helper"
+
+class DirectoInvoiceForwardJobTest < ActiveSupport::TestCase
+ setup do
+ @invoice = invoices(:one)
+ @user = registrars(:bestnames)
+ travel_to Time.zone.parse('2010-08-06')
+ end
+
+ def teardown
+ Setting.clear_cache
+ Setting.directo_monthly_number_min = 309901
+ Setting.directo_monthly_number_max = 309999
+ Setting.directo_monthly_number_last = 309901
+ end
+
+ def test_xml_is_include_transaction_date
+ @invoice.update(total: @invoice.account_activity.bank_transaction.sum)
+ @invoice.account_activity.bank_transaction.update(paid_at: Time.zone.now)
+
+ response = <<-XML
+
+
+
+
+ XML
+
+ stub_request(:post, ENV['directo_invoice_url']).with do |request|
+ request.body.include? 'TransactionDate'
+ end.to_return(status: 200, body: response)
+
+ assert_nothing_raised do
+ DirectoInvoiceForwardJob.run(monthly: false, dry: false)
+ end
+
+ assert_not_empty @invoice.directo_records.first.request
+ end
+
+ def test_fails_if_directo_bounds_exceedable
+ activity = account_activities(:one)
+ price = billing_prices(:create_one_year)
+ activity.update!(activity_type: 'create', price: price)
+
+ Setting.directo_monthly_number_max = 30991
+
+ assert_raises 'RuntimeError' do
+ DirectoInvoiceForwardJob.run(monthly: true, dry: false)
+ end
+ end
+
+ def test_monthly_summary_is_delivered_in_estonian
+ activity = account_activities(:one)
+ price = billing_prices(:create_one_year)
+ activity.update!(activity_type: 'create', price: price)
+ @user.update(language: 'et')
+
+ response = <<-XML
+
+
+
+
+ XML
+
+ stub_request(:post, ENV['directo_invoice_url']).with do |request|
+ body = CGI.unescape(request.body)
+
+ (body.include? '.test registreerimine: 1 aasta(t)') &&
+ (body.include? 'Domeenide ettemaks') &&
+ (body.include? '309902')
+ end.to_return(status: 200, body: response)
+
+ assert_difference 'Setting.directo_monthly_number_last' do
+ DirectoInvoiceForwardJob.run(monthly: true, dry: false)
+ end
+ end
+
+ def test_monthly_summary_is_delivered_in_english
+ activity = account_activities(:one)
+ price = billing_prices(:create_one_year)
+ activity.update(activity_type: 'create', price: price)
+ @user.update(language: 'en')
+
+ response = <<-XML
+
+
+
+
+ XML
+
+ stub_request(:post, ENV['directo_invoice_url']).with do |request|
+ body = CGI.unescape(request.body)
+ (body.include? 'test registration') &&
+ (body.include? 'Domains prepayment') &&
+ (body.include? '309902')
+ end.to_return(status: 200, body: response)
+
+ assert_difference 'Setting.directo_monthly_number_last' do
+ DirectoInvoiceForwardJob.run(monthly: true, dry: false)
+ end
+ end
+
+ def test_multi_year_purchases_have_duration_assigned
+ activity = account_activities(:one)
+ price = billing_prices(:create_one_year)
+ price.update(duration: '3 years')
+ activity.update(activity_type: 'create', price: price)
+
+ response = <<-XML
+
+
+
+
+ XML
+
+ stub_request(:post, ENV['directo_invoice_url']).with do |request|
+ body = CGI.unescape(request.body)
+ (body.include? 'StartDate') && (body.include? 'EndDate')
+ end.to_return(status: 200, body: response)
+
+ assert_difference 'Setting.directo_monthly_number_last' do
+ DirectoInvoiceForwardJob.run(monthly: true, dry: false)
+ end
+ end
+
+ def test_monthly_duration_products_are_present_in_summary
+ activity = account_activities(:one)
+ price = billing_prices(:create_one_month)
+ activity.update(activity_type: 'create', price: price)
+
+ response = <<-XML
+
+
+
+
+ XML
+
+ stub_request(:post, ENV['directo_invoice_url']).with do |request|
+ body = CGI.unescape(request.body)
+ body.include? 'month(s)'
+ end.to_return(status: 200, body: response)
+
+ assert_difference 'Setting.directo_monthly_number_last' do
+ DirectoInvoiceForwardJob.run(monthly: true, dry: false)
+ end
+ end
+end
diff --git a/test/jobs/send_e_invoice_job_test.rb b/test/jobs/send_e_invoice_job_test.rb
new file mode 100644
index 000000000..384479e92
--- /dev/null
+++ b/test/jobs/send_e_invoice_job_test.rb
@@ -0,0 +1,47 @@
+require 'test_helper'
+
+class SendEInvoiceJobTest < ActiveSupport::TestCase
+
+ def teardown
+ EInvoice.provider = EInvoice::Providers::TestProvider.new
+ EInvoice::Providers::TestProvider.deliveries.clear
+ end
+
+ def test_if_invoice_is_sended
+ @invoice = invoices(:one)
+ EInvoice.provider = EInvoice::Providers::TestProvider.new
+ EInvoice::Providers::TestProvider.deliveries.clear
+
+ assert_nothing_raised do
+ SendEInvoiceJob.enqueue(@invoice.id)
+ end
+ @invoice.reload
+
+ assert_not @invoice.e_invoice_sent_at.blank?
+ assert_equal 1, EInvoice::Providers::TestProvider.deliveries.count
+ end
+
+ def test_if_invoice_sending_retries
+ @invoice = invoices(:one)
+ provider_config = { password: nil,
+ test_mode: true }
+ EInvoice.provider = EInvoice::Providers::OmnivaProvider.new(provider_config)
+ stub_request(:get, "https://testfinance.post.ee/finance/erp/erpServices.wsdl").to_timeout
+
+ assert_raise HTTPClient::TimeoutError do
+ SendEInvoiceJob.enqueue(@invoice.id)
+ end
+ assert @invoicee_invoice_sent_at.blank?
+
+ EInvoice.provider = EInvoice::Providers::TestProvider.new
+ EInvoice::Providers::TestProvider.deliveries.clear
+
+ assert_nothing_raised do
+ SendEInvoiceJob.enqueue(@invoice.id)
+ end
+ @invoice.reload
+
+ assert_not @invoice.e_invoice_sent_at.blank?
+ assert_equal 1, EInvoice::Providers::TestProvider.deliveries.count
+ end
+end
diff --git a/test/learning/paper_trail_test.rb b/test/learning/paper_trail_test.rb
index 9396496b7..b7351c644 100644
--- a/test/learning/paper_trail_test.rb
+++ b/test/learning/paper_trail_test.rb
@@ -21,6 +21,25 @@ class PaperTrailLearningTest < ActiveSupport::TestCase
assert_respond_to @record.versions.first, :item_id
end
+ def test_returns_version_count_on_domains
+ @domain = domains(:airport)
+ @domain.save
+
+ assert_equal 1, @domain.versions.count
+
+ @domain.name = 'domain.test'
+ @domain.save!
+ assert_equal 2, @domain.versions.count
+ end
+
+ def test_returns_version_count_on_users
+ @user = users(:registrant)
+
+ @user.email = 'aaa@bbb.com'
+ @user.save!
+ assert_equal 1, @user.versions.count
+ end
+
def test_creates_new_version_upon_update
@record = Post.create!(title: 'old title')
original_record = @record.clone
@@ -40,7 +59,7 @@ class PaperTrailLearningTest < ActiveSupport::TestCase
@record = Post.create!(title: 'any')
assert_difference -> { @record.versions.size } do
- @record.touch_with_version
+ @record.paper_trail.touch_with_version
end
end
-end
\ No newline at end of file
+end
diff --git a/test/models/deposit_test.rb b/test/models/deposit_test.rb
index d8fc2d02a..171316f65 100644
--- a/test/models/deposit_test.rb
+++ b/test/models/deposit_test.rb
@@ -36,22 +36,22 @@ class DepositTest < ActiveSupport::TestCase
def test_amount_is_converted_from_string
@deposit.amount = "12.00"
- assert_equal(BigDecimal.new("12.00"), @deposit.amount)
+ assert_equal(BigDecimal("12.00"), @deposit.amount)
@deposit.amount = "12,11"
- assert_equal(BigDecimal.new("12.11"), @deposit.amount)
+ assert_equal(BigDecimal("12.11"), @deposit.amount)
end
def test_amount_is_converted_from_float
@deposit.amount = 12.0044
- assert_equal(BigDecimal.new("12.0044"), @deposit.amount)
+ assert_equal(BigDecimal("12.0044"), @deposit.amount)
@deposit.amount = 12.0144
- assert_equal(BigDecimal.new("12.0144"), @deposit.amount)
+ assert_equal(BigDecimal("12.0144"), @deposit.amount)
end
def test_amount_is_converted_from_nil
@deposit.amount = nil
- assert_equal(BigDecimal.new("0.00"), @deposit.amount)
+ assert_equal(BigDecimal("0.00"), @deposit.amount)
end
end
diff --git a/test/models/directo_test.rb b/test/models/directo_test.rb
index 9dbbf64d4..603a38d15 100644
--- a/test/models/directo_test.rb
+++ b/test/models/directo_test.rb
@@ -1,20 +1,4 @@
require 'test_helper'
class DirectoTest < ActiveSupport::TestCase
- setup do
- @invoice = invoices(:one)
- end
-
- def test_xml_is_include_transaction_date
- @invoice.update(total: @invoice.account_activity.bank_transaction.sum)
- @invoice.account_activity.bank_transaction.update(paid_at: Time.zone.now)
-
- stub_request(:post, ENV['directo_invoice_url']).with do |request|
- request.body.include? 'TransactionDate'
- end
-
- assert_nothing_raised do
- Directo.send_receipts
- end
- end
end
diff --git a/test/models/dns/domain_name_test.rb b/test/models/dns/domain_name_test.rb
index bd83076bc..4f8922d32 100644
--- a/test/models/dns/domain_name_test.rb
+++ b/test/models/dns/domain_name_test.rb
@@ -13,6 +13,8 @@ class AuctionDoubleTest < ActiveSupport::TestCase
end
class DNS::DomainNameTest < ActiveSupport::TestCase
+ fixtures 'whois/records'
+
def test_available_when_not_at_auction
domain_name = DNS::DomainName.new('auction.test')
auctions(:one).update!(domain: 'auction.test', status: Auction.statuses[:domain_registered])
diff --git a/test/models/payment_orders/bank_link_test.rb b/test/models/payment_orders/bank_link_test.rb
index 002f488b9..30d91cb7c 100644
--- a/test/models/payment_orders/bank_link_test.rb
+++ b/test/models/payment_orders/bank_link_test.rb
@@ -8,7 +8,7 @@ class BankLinkTest < ActiveSupport::TestCase
super
@invoice = invoices(:one)
- @invoice.update!(total: 12)
+ @invoice.update!(account_activity: nil, total: 12)
travel_to '2018-04-01 00:30 +0300'
create_new_bank_link
@@ -36,11 +36,11 @@ class BankLinkTest < ActiveSupport::TestCase
'VK_MAC': 'CZZvcptkxfuOxRR88JmT4N+Lw6Hs4xiQfhBWzVYldAcRTQbcB/lPf9MbJzBE4e1/HuslQgkdCFt5g1xW2lJwrVDBQTtP6DAHfvxU3kkw7dbk0IcwhI4whUl68/QCwlXEQTAVDv1AFnGVxXZ40vbm/aLKafBYgrirB5SUe8+g9FE=',
'VK_ENCODING': 'UTF-8',
'VK_LANG': 'ENG'
- }.with_indifferent_access
+ }.as_json
- @completed_bank_link = PaymentOrders::BankLink.new(
- 'seb', @invoice, { response: params }
- )
+ @completed_bank_link = PaymentOrder.new(type: 'PaymentOrders::Seb',
+ invoice: @invoice,
+ response: params)
end
def create_cancelled_bank_link
@@ -55,16 +55,17 @@ class BankLinkTest < ActiveSupport::TestCase
'VK_MAC': 'PElE2mYXXN50q2UBvTuYU1rN0BmOQcbafPummDnWfNdm9qbaGQkGyOn0XaaFGlrdEcldXaHBbZKUS0HegIgjdDfl2NOk+wkLNNH0Iu38KzZaxHoW9ga7vqiyKHC8dcxkHiO9HsOnz77Sy/KpWCq6cz48bi3fcMgo+MUzBMauWoQ=',
'VK_ENCODING': 'UTF-8',
'VK_LANG': 'ENG'
- }.with_indifferent_access
+ }.as_json
- @cancelled_bank_link = PaymentOrders::BankLink.new(
- 'seb', @invoice, { response: params }
- )
+ @cancelled_bank_link = PaymentOrder.new(type: 'PaymentOrders::Seb',
+ invoice: @invoice,
+ response: params)
end
def create_new_bank_link
- params = { return_url: 'return.url', response_url: 'response.url' }
- @new_bank_link = PaymentOrders::BankLink.new('seb', @invoice, params)
+ @new_bank_link = PaymentOrder.new(type: 'PaymentOrders::Seb', invoice: @invoice)
+ @new_bank_link.return_url = 'return.url'
+ @new_bank_link.response_url = 'response.url'
end
def test_response_is_not_valid_when_it_is_missing
@@ -105,23 +106,14 @@ class BankLinkTest < ActiveSupport::TestCase
refute(@cancelled_bank_link.settled_payment?)
end
- def test_complete_transaction_calls_methods_on_transaction
- mock_transaction = MiniTest::Mock.new
- mock_transaction.expect(:sum= , '12.00', ['12.00'])
- mock_transaction.expect(:bank_reference= , '1', ['1'])
- mock_transaction.expect(:buyer_bank_code= , 'testvpos', ['testvpos'])
- mock_transaction.expect(:buyer_iban= , '1234', ['1234'])
- mock_transaction.expect(:paid_at= , Date.parse('2018-04-01 00:30:00 +0300'), [Time.parse('2018-04-01T00:30:00+0300')])
- mock_transaction.expect(:buyer_name=, 'John Doe', ['John Doe'])
- mock_transaction.expect(:save!, true)
- mock_transaction.expect(:binded?, false)
- mock_transaction.expect(:bind_invoice, AccountActivity.new, [1])
- mock_transaction.expect(:errors, [])
+ def test_successful_payment_creates_bank_transaction
+ @completed_bank_link.complete_transaction
- BankTransaction.stub(:find_by, mock_transaction) do
- @completed_bank_link.complete_transaction
- end
+ transaction = BankTransaction.find_by(
+ sum: @completed_bank_link.response['VK_AMOUNT'],
+ buyer_name: @completed_bank_link.response['VK_SND_NAME']
+ )
- mock_transaction.verify
+ assert transaction.present?
end
end
diff --git a/test/models/payment_orders/every_pay_test.rb b/test/models/payment_orders/every_pay_test.rb
index 81e077b23..1e560f32a 100644
--- a/test/models/payment_orders/every_pay_test.rb
+++ b/test/models/payment_orders/every_pay_test.rb
@@ -4,36 +4,38 @@ class EveryPayTest < ActiveSupport::TestCase
def setup
super
- @invoice = invoices(:one)
+ @invoice = invoices(:unpaid)
@invoice.update!(total: 12)
- params = {
- response:
- {
- utf8: '✓',
- _method: 'put',
- authenticity_token: 'OnA69vbccQtMt3C9wxEWigs5Gpf/7z+NoxRCMkFPlTvaATs8+OgMKF1I4B2f+vuK37zCgpWZaWWtyuslRRSwkw==',
- nonce: '392f2d7748bc8cb0d14f263ebb7b8932',
- timestamp: '1524136727',
- api_username: 'ca8d6336dd750ddb',
- transaction_result: 'completed',
- payment_reference: 'fd5d27b59a1eb597393cd5ff77386d6cab81ae05067e18d530b10f3802e30b56',
- payment_state: 'settled',
- amount: '12.00',
- order_reference: 'e468a2d59a731ccc546f2165c3b1a6',
- account_id: 'EUR3D1',
- cc_type: 'master_card',
- cc_last_four_digits: '0487',
- cc_month: '10',
- cc_year: '2018',
- cc_holder_name: 'John Doe',
- hmac_fields: 'account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result',
- hmac: 'efac1c732835668cd86023a7abc140506c692f0d',
- invoice_id: '1',
- },
- }
- @every_pay = PaymentOrders::EveryPay.new('every_pay', @invoice, params)
- @other_pay = PaymentOrders::EveryPay.new('every_pay', @invoice, {})
+ response = {
+ "utf8": '✓',
+ "_method": 'put',
+ "authenticity_token": 'OnA69vbccQtMt3C9wxEWigs5Gpf/7z+NoxRCMkFPlTvaATs8+OgMKF1I4B2f+vuK37zCgpWZaWWtyuslRRSwkw=="',
+ "nonce": '392f2d7748bc8cb0d14f263ebb7b8932',
+ "timestamp": '1524136727',
+ "api_username": 'ca8d6336dd750ddb',
+ "transaction_result": 'completed',
+ "payment_reference": 'fd5d27b59a1eb597393cd5ff77386d6cab81ae05067e18d530b10f3802e30b56',
+ "payment_state": 'settled',
+ "amount": '12.00',
+ "order_reference": 'e468a2d59a731ccc546f2165c3b1a6',
+ "account_id": 'EUR3D1',
+ "cc_type": 'master_card',
+ "cc_last_four_digits": '0487',
+ "cc_month": '10',
+ "cc_year": '2018',
+ "cc_holder_name": 'John Doe',
+ "hmac_fields": 'account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result',
+ "hmac": 'efac1c732835668cd86023a7abc140506c692f0d',
+ "invoice_id": '2'
+ }.as_json
+
+ @successful_payment = PaymentOrder.new(type: 'PaymentOrders::EveryPay',
+ invoice: @invoice,
+ response: response)
+
+ @failed_payment = @successful_payment.dup
+ @failed_payment.response['payment_state'] = 'cancelled'
travel_to Time.zone.parse('2018-04-01 00:30:00 +0000')
end
@@ -47,39 +49,37 @@ class EveryPayTest < ActiveSupport::TestCase
transaction_type: 'charge',
hmac_fields: 'account_id,amount,api_username,callback_url,customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type'
}
- form_fields = @every_pay.form_fields
+ form_fields = @successful_payment.form_fields
expected_fields.each do |k, v|
assert_equal(v, form_fields[k])
end
end
def test_valid_response_from_intermediary?
- assert(@every_pay.valid_response_from_intermediary?)
- refute(@other_pay.valid_response_from_intermediary?)
+ assert(@successful_payment.valid_response_from_intermediary?)
+
+ @failed_payment.response = { 'what': 'definitely not valid everypay response' }
+ refute(@failed_payment.valid_response_from_intermediary?)
+ end
+
+ def test_valid_and_successful_payment_is_determined
+ assert(@successful_payment.payment_received?)
+ refute(@failed_payment.payment_received?)
end
def test_settled_payment?
- assert(@every_pay.settled_payment?)
- other_pay = PaymentOrders::EveryPay.new(
- 'every_pay', @invoice, {response: {payment_state: 'CANCELLED'}}
- )
- refute(other_pay.settled_payment?)
+ assert(@successful_payment.settled_payment?)
+ refute(@failed_payment.settled_payment?)
end
- def test_complete_transaction_calls_methods_on_transaction
- mock_transaction = MiniTest::Mock.new
- mock_transaction.expect(:sum= , '12.00', ['12.00'])
- mock_transaction.expect(:paid_at= , Date.strptime('1524136727', '%s'), [Date.strptime('1524136727', '%s')])
- mock_transaction.expect(:buyer_name=, 'John Doe', ['John Doe'])
- mock_transaction.expect(:save!, true)
- mock_transaction.expect(:binded?, false)
- mock_transaction.expect(:bind_invoice, AccountActivity.new, [1])
- mock_transaction.expect(:errors, [])
+ def test_successful_payment_creates_bank_transaction
+ @successful_payment.complete_transaction
- BankTransaction.stub(:find_by, mock_transaction) do
- @every_pay.complete_transaction
- end
+ transaction = BankTransaction.find_by(
+ sum: @successful_payment.response['amount'],
+ buyer_name: @successful_payment.response['cc_holder_name']
+ )
- mock_transaction.verify
+ assert transaction.present?
end
end
diff --git a/test/models/payment_orders_test.rb b/test/models/payment_orders_test.rb
index 252ba0582..43996c6bc 100644
--- a/test/models/payment_orders_test.rb
+++ b/test/models/payment_orders_test.rb
@@ -5,23 +5,21 @@ class PaymentOrdersTest < ActiveSupport::TestCase
super
@original_methods = ENV['payment_methods']
- @original_seb_URL = ENV['seb_payment_url']
- ENV['payment_methods'] = 'seb, swed, credit_card'
+ @original_seb_url = ENV['seb_payment_url']
+ ENV['payment_methods'] = 'seb, swed, every_pay'
ENV['seb_payment_url'] = nil
- @not_implemented_payment = PaymentOrders::Base.new(
- 'not_implemented', Invoice.new
- )
+ @not_implemented_payment = PaymentOrder.new(invoice: Invoice.new)
end
def teardown
super
ENV['payment_methods'] = @original_methods
- ENV['seb_payment_url'] = @original_seb_URL
+ ENV['seb_payment_url'] = @original_seb_url
end
def test_variable_assignment
- assert_equal 'not_implemented', @not_implemented_payment.type
+ assert_nil @not_implemented_payment.type
assert_nil @not_implemented_payment.response_url
assert_nil @not_implemented_payment.return_url
assert_nil @not_implemented_payment.form_url
@@ -45,14 +43,61 @@ class PaymentOrdersTest < ActiveSupport::TestCase
end
end
- def test_that_create_with_type_raises_argument_error
- assert_raise ArgumentError do
- PaymentOrders.create_with_type("not_implemented", Invoice.new)
+ def test_correct_channel_is_assigned
+ everypay_channel = PaymentOrder.new_with_type(type: 'every_pay', invoice: @invoice)
+ assert_equal everypay_channel.channel, 'EveryPay'
+ assert_equal everypay_channel.class.config_namespace_name, 'every_pay'
+
+ swed_channel = PaymentOrder.new_with_type(type: 'swed', invoice: @invoice)
+ assert_equal swed_channel.channel, 'Swed'
+ assert_equal swed_channel.class.config_namespace_name, 'swed'
+
+ seb_channel = PaymentOrder.new_with_type(type: 'seb', invoice: @invoice)
+ assert_equal seb_channel.channel, 'Seb'
+ assert_equal seb_channel.class.config_namespace_name, 'seb'
+
+ lhv_channel = PaymentOrder.new_with_type(type: 'lhv', invoice: @invoice)
+ assert_equal lhv_channel.channel, 'Lhv'
+ assert_equal lhv_channel.class.config_namespace_name, 'lhv'
+
+ admin_channel = PaymentOrder.new_with_type(type: 'admin_payment', invoice: @invoice)
+ assert_equal admin_channel.channel, 'AdminPayment'
+ assert_equal admin_channel.class.config_namespace_name, 'admin_payment'
+
+ system_channel = PaymentOrder.new_with_type(type: 'system_payment', invoice: @invoice)
+ assert_equal system_channel.channel, 'SystemPayment'
+ assert_equal system_channel.class.config_namespace_name, 'system_payment'
+ end
+
+ def test_can_not_create_order_for_paid_invoice
+ invoice = invoices(:one)
+ payment_order = PaymentOrder.new_with_type(type: 'every_pay', invoice: invoice)
+ assert payment_order.invalid?
+ assert_includes payment_order.errors[:invoice], 'is already paid'
+ end
+
+ def test_order_without_channel_is_invalid
+ payment_order = PaymentOrder.new
+ assert payment_order.invalid?
+ assert_includes payment_order.errors[:type], 'is not supported'
+ end
+
+ def test_can_not_create_order_with_invalid_type
+ assert_raise NameError do
+ PaymentOrder.new_with_type(type: 'not_implemented', invoice: Invoice.new)
end
end
- def test_create_with_correct_subclass
- payment = PaymentOrders.create_with_type('seb', Invoice.new)
- assert_equal PaymentOrders::BankLink, payment.class
+ def test_supported_method_bool_does_not_fail
+ assert_not PaymentOrder.supported_method?('not_implemented', shortname: true)
+ assert PaymentOrder.supported_method?('every_pay', shortname: true)
+
+ assert_not PaymentOrder.supported_method?('PaymentOrders::NonExistant')
+ assert PaymentOrder.supported_method?('PaymentOrders::EveryPay')
+ end
+
+ def test_can_create_with_correct_subclass
+ payment = PaymentOrder.new_with_type(type: 'seb', invoice: Invoice.new)
+ assert_equal PaymentOrders::Seb, payment.class
end
end
diff --git a/test/support/rails5_assertions.rb b/test/support/rails5_assertions.rb
deleted file mode 100644
index a11bb3ef1..000000000
--- a/test/support/rails5_assertions.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-# Built-in since Rails 5.1
-
-module ActiveSupport
- module Testing
- module Assertions
- UNTRACKED = Object.new # :nodoc:
-
- # Assertion that the result of evaluating an expression is changed before
- # and after invoking the passed in block.
- #
- # assert_changes 'Status.all_good?' do
- # post :create, params: { status: { ok: false } }
- # end
- #
- # You can pass the block as a string to be evaluated in the context of
- # the block. A lambda can be passed for the block as well.
- #
- # assert_changes -> { Status.all_good? } do
- # post :create, params: { status: { ok: false } }
- # end
- #
- # The assertion is useful to test side effects. The passed block can be
- # anything that can be converted to string with #to_s.
- #
- # assert_changes :@object do
- # @object = 42
- # end
- #
- # The keyword arguments :from and :to can be given to specify the
- # expected initial value and the expected value after the block was
- # executed.
- #
- # assert_changes :@object, from: nil, to: :foo do
- # @object = :foo
- # end
- #
- # An error message can be specified.
- #
- # assert_changes -> { Status.all_good? }, 'Expected the status to be bad' do
- # post :create, params: { status: { incident: true } }
- # end
- def assert_changes(expression, message = nil, from: UNTRACKED, to: UNTRACKED, &block)
- exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
-
- before = exp.call
- retval = yield
-
- unless from == UNTRACKED
- error = "#{expression.inspect} isn't #{from.inspect}"
- error = "#{message}.\n#{error}" if message
- assert from === before, error
- end
-
- after = exp.call
-
- if to == UNTRACKED
- error = "#{expression.inspect} didn't changed"
- error = "#{message}.\n#{error}" if message
- assert_not_equal before, after, error
- else
- error = "#{expression.inspect} didn't change to #{to}"
- error = "#{message}.\n#{error}" if message
- assert to === after, error
- end
-
- retval
- end
-
- # Assertion that the result of evaluating an expression is changed before
- # and after invoking the passed in block.
- #
- # assert_no_changes 'Status.all_good?' do
- # post :create, params: { status: { ok: true } }
- # end
- #
- # An error message can be specified.
- #
- # assert_no_changes -> { Status.all_good? }, 'Expected the status to be good' do
- # post :create, params: { status: { ok: false } }
- # end
- def assert_no_changes(expression, message = nil, &block)
- exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
-
- before = exp.call
- retval = yield
- after = exp.call
-
- error = "#{expression.inspect} did change to #{after}"
- error = "#{message}.\n#{error}" if message
- assert_equal before, after, error
-
- retval
- end
- end
- end
-end
diff --git a/test/system/admin_area/bank_statement_test.rb b/test/system/admin_area/bank_statement_test.rb
new file mode 100644
index 000000000..c95035a8d
--- /dev/null
+++ b/test/system/admin_area/bank_statement_test.rb
@@ -0,0 +1,16 @@
+require 'application_system_test_case'
+
+class BankStatementTest < ApplicationSystemTestCase
+ setup do
+ sign_in users(:admin)
+ travel_to Time.zone.parse('2010-07-05 00:30:00')
+ end
+
+ def test_import_statement
+ assert_difference 'BankStatement.count', 1 do
+ visit import_admin_bank_statements_path
+ attach_file 'Th6 file', Rails.root.join('test', 'fixtures', 'files', 'bank_statement_test.txt').to_s
+ click_link_or_button 'Save'
+ end
+ end
+end
diff --git a/test/system/admin_area/domains_test.rb b/test/system/admin_area/domains_test.rb
index abd1d93fb..05e7d60f3 100644
--- a/test/system/admin_area/domains_test.rb
+++ b/test/system/admin_area/domains_test.rb
@@ -35,4 +35,15 @@ class AdminDomainsTestTest < ApplicationSystemTestCase
assert_text 'deleteCandidate status has been removed'
assert_no_link 'Remove deleteCandidate status'
end
+
+ def test_remove_domain_status
+ @domain.update!(statuses: [DomainStatus::SERVER_REGISTRANT_CHANGE_PROHIBITED])
+
+ visit edit_admin_domain_url(@domain)
+
+ click_link_or_button 'Delete'
+ click_link_or_button 'Save'
+
+ assert_text 'Domain updated!'
+ end
end
diff --git a/test/tasks/data_migrations/convert_domain_delete_date_test.rb b/test/tasks/data_migrations/convert_domain_delete_date_test.rb
deleted file mode 100644
index 709334b52..000000000
--- a/test/tasks/data_migrations/convert_domain_delete_date_test.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-require 'test_helper'
-
-class ConvertDomainDeleteDateTaskTest < ActiveSupport::TestCase
- setup do
- @domain = domains(:shop)
- end
-
- def test_moves_domain_delete_date_one_day_ahead
- @domain.update!(delete_date: '2010-07-05')
-
- capture_io do
- run_task
- end
- @domain.reload
-
- assert_equal Date.parse('2010-07-06'), @domain.delete_date
- end
-
- def test_processes_invalid_domains
- @domain = domains(:invalid)
- @domain.update_columns(delete_date: '2010-07-05')
-
- capture_io do
- run_task
- end
- @domain.reload
-
- assert_equal Date.parse('2010-07-06'), @domain.delete_date
- end
-
- def test_skips_non_expired_domains
- @domain.update!(delete_date: nil)
-
- assert_nothing_raised do
- capture_io do
- run_task
- end
- end
- end
-
- def test_output
- eliminate_effect_of_all_domains_except(@domain)
- @domain.update!(delete_date: '2010-07-05')
-
- assert_output "Domains processed: 1\n" do
- run_task
- end
- end
-
- private
-
- def eliminate_effect_of_all_domains_except(domain)
- Domain.connection.disable_referential_integrity do
- Domain.where("id != #{domain.id}").delete_all
- end
- end
-
- def run_task
- Rake::Task['data_migrations:convert_domain_delete_date'].execute
- end
-end
\ No newline at end of file
diff --git a/test/tasks/data_migrations/delete_orphaned_registrant_verifications_test.rb b/test/tasks/data_migrations/delete_orphaned_registrant_verifications_test.rb
deleted file mode 100644
index df576332e..000000000
--- a/test/tasks/data_migrations/delete_orphaned_registrant_verifications_test.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-require 'test_helper'
-
-class ArchiveOrphanedRegistrantVerificationsTest < ActiveSupport::TestCase
- def test_deletes_orphaned_registrant_verifications
- create_orphaned_registrant_verification
-
- assert_difference 'RegistrantVerification.count', -1 do
- capture_io do
- run_task
- end
- end
- end
-
- def test_keeps_non_orphaned_registrant_verifications_intact
- assert_no_difference 'RegistrantVerification.count' do
- capture_io do
- run_task
- end
- end
- end
-
- def test_output
- create_orphaned_registrant_verification
-
- assert_output "Processed: 1 out of 1\n" do
- run_task
- end
- end
-
- private
-
- def create_orphaned_registrant_verification
- non_existent_domain_id = 55
- assert_not_includes Domain.ids, non_existent_domain_id
-
- RegistrantVerification.connection.disable_referential_integrity do
- registrant_verifications(:one).update_columns(domain_id: non_existent_domain_id)
- end
- end
-
- def run_task
- Rake::Task['data_migrations:delete_orphaned_registrant_verifications'].execute end
-end
diff --git a/test/tasks/invoices/process_payments_test.rb b/test/tasks/invoices/process_payments_test.rb
index 8c3b6ec73..02855e9fa 100644
--- a/test/tasks/invoices/process_payments_test.rb
+++ b/test/tasks/invoices/process_payments_test.rb
@@ -58,6 +58,30 @@ class ProcessPaymentsTaskTest < ActiveSupport::TestCase
assert @invoice.paid?
end
+ def test_attaches_paid_payment_order_to_invoice
+ assert @invoice.unpaid?
+
+ capture_io { run_task }
+ @invoice.reload
+
+ payment_order = @invoice.payment_orders.last
+ assert_equal 'PaymentOrders::SystemPayment', payment_order.type
+ assert payment_order.paid?
+ end
+
+ def test_attaches_failed_payment_order_to_invoice
+ assert @invoice.unpaid?
+ account = accounts(:cash)
+ account.update!(registrar: registrars(:goodnames))
+
+ capture_io { run_task }
+ @invoice.reload
+
+ payment_order = @invoice.payment_orders.last
+ assert_equal 'PaymentOrders::SystemPayment', payment_order.type
+ assert payment_order.failed?
+ end
+
def test_output
assert_output "Transactions processed: 1\n" do
run_task
@@ -75,4 +99,4 @@ class ProcessPaymentsTaskTest < ActiveSupport::TestCase
invoice.update!({ account_activity: nil, cancelled_at: nil }.merge(attributes))
invoice
end
-end
\ No newline at end of file
+end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 4cd632ea2..efdbc288f 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -16,7 +16,6 @@ require 'minitest/mock'
require 'capybara/rails'
require 'capybara/minitest'
require 'webmock/minitest'
-require 'support/rails5_assertions' # Remove once upgraded to Rails 5.1
require 'support/assertions/epp_assertions'