diff --git a/.github/workflows/build_baseimage_with_gems.yml b/.github/workflows/build_baseimage_with_gems.yml index 3487e838c..e6f72594a 100644 --- a/.github/workflows/build_baseimage_with_gems.yml +++ b/.github/workflows/build_baseimage_with_gems.yml @@ -17,7 +17,7 @@ jobs: steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Login to container registry env: diff --git a/.github/workflows/build_deploy_staging.yml b/.github/workflows/build_deploy_staging.yml index e339353f2..b854ce820 100644 --- a/.github/workflows/build_deploy_staging.yml +++ b/.github/workflows/build_deploy_staging.yml @@ -67,7 +67,7 @@ jobs: - name: Set EPP port run: echo "EPP_PORT=${PR_REF:(-3)}" >> $GITHUB_ENV - + - name: Set config files for build env: ST_APP: ${{ secrets.ST_APPLICATION_YML}} @@ -101,7 +101,7 @@ jobs: sed -i -e 's/{certfile_path, "\/opt\/shared\/ca\/certs\/cert.pem"},/{certfile_path, "\/opt\/shared\/ca\/certs\/tls.crt"},/' sys.config sed -i -e 's/{keyfile_path, "\/opt\/shared\/ca\/certs\/key.pem"},/{keyfile_path, "\/opt\/shared\/ca\/certs\/tls.key"}]},/' sys.config sed -i -e 's/{crlfile_path, "\/opt\/shared\/ca\/certs\/key.pem"}]},//' sys.config - + - name: Build proxy image run: | cd epp_proxy @@ -143,7 +143,9 @@ jobs: chmod 0600 kubeconfig - name: Install Open VPN - run: sudo apt-get install openvpn + run: | + sudo apt-get update + sudo apt-get install openvpn - name: Deploy from remote server timeout-minutes: 5 diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index dd71c4bee..d50636e26 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -22,7 +22,7 @@ jobs: continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} @@ -79,7 +79,7 @@ jobs: - name: Save coverage run: ./cc-test-reporter format-coverage --output coverage/codeclimate.${{ matrix.ruby }}.json - - uses: actions/upload-artifact@v2.3.1 + - uses: actions/upload-artifact@v3.0.0 with: name: coverage-${{ matrix.ruby }} path: coverage/codeclimate.${{ matrix.ruby }}.json @@ -104,7 +104,7 @@ jobs: - name: Give test coverage reporter executable permissions run: chmod +x cc-test-reporter - - uses: actions/download-artifact@v2.1.0 + - uses: actions/download-artifact@v3.0.0 with: name: coverage-${{ matrix.ruby }} path: coverage diff --git a/.gitignore b/.gitignore index 3f23f1277..1c4a85f46 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ /config/application.yml /config/environments/development.rb /config/deploy.rb +/config/master.key /.idea # Do not commit one. Instead, download the latest from https://github.com/internetee/style-guide. diff --git a/CHANGELOG.md b/CHANGELOG.md index 893557f80..944496e95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,72 @@ +17.05.2022 +* removed unnecessary contact validation on contact create [#2376](https://github.com/internetee/registry/pull/2376) +* Refactored email validation job [#2369](https://github.com/internetee/registry/pull/2369) +* Job for deprecated validation events removal [#2374](https://github.com/internetee/registry/issues/2374) + +09.05.2022 +* test for auction view [#2373](https://github.com/internetee/registry/pull/2373) + +06.05.2022 +* refactored out the contact_code_cache from domain_contacts model [#2370](https://github.com/internetee/registry/issues/2370) + +28.04.2022 +* Fixed ns and dnssec validation error messages [#2296](https://github.com/internetee/registry/issues/2296) +* Added status notes to REPP domain info output [#2331](https://github.com/internetee/registry/issues/2331) +* Added auction list view to admin for improved ahandling of upcoming enlgish auction feature [#2341](https://github.com/internetee/registry/pull/2341) + +27.04.2022 +* Refactored email validation - reducing dns requests [#2364](https://github.com/internetee/registry/issues/2364) + +21.04.2022 +* Delay renovate Ruby version updates for 60 days [#2361](https://github.com/internetee/registry/issues/2361) + +20.04.2022 +* Contacts with disclosed attributes can now be updated [#2340](https://github.com/internetee/registry/issues/2340) +* Legacy code fix [#2360](https://github.com/internetee/registry/pull/2360) + +19.04.2022 +* Rolled back ruby version to 3.0.3 [#2358](https://github.com/internetee/registry/pull/2358) + +18.04.2022 +* Fixed error 2005 epp syntax issue [#2338](https://github.com/internetee/registry/issues/2338) +* Fixed poll issue with email validations [#2343](https://github.com/internetee/registry/issues/2343) +* Removed registrant portal code from registry project [#2350](https://github.com/internetee/registry/issues/2350) + +14.04.2022 +* Removed legacy email verification code [#2349](https://github.com/internetee/registry/issues/2349) + +06.04.2022 +* Contact email validation on domain update [#2213](https://github.com/internetee/registry/issues/2213) + +05.04.2022 +* Automatic contact name update poll messages are now grouped together into one change poll message [#2307](https://github.com/internetee/registry/issues/2307) +* Status notes are now added to status elements of epp xml [#2211](https://github.com/internetee/registry/issues/2211) +* Admin: Wildcard search improvements [#499](https://github.com/internetee/registry/issues/499) +* Admin: CSV download fix for history view [#2275](https://github.com/internetee/registry/issues/2275) +* Admin: CSV output fix for diman, contact, invoices and account views [2303](https://github.com/internetee/registry/issues/2303) +* Admin: registrar dropdown is searchable in invoice creation view [#2313](https://github.com/internetee/registry/issues/2313) +* Admin: Refactored CSV generation [#2321](https://github.com/internetee/registry/issues/2321) +* Removed legacy migration jobs [#2090](https://github.com/internetee/registry/issues/2090) + +04.04.2022 +* Upload-artifact update to 3.0.0 [#2301](https://github.com/internetee/registry/pull/2301) +* data_migrate update to 8.0 [#2302](https://github.com/internetee/registry/pull/2302) + +01.04.2022 +* Pg update to 1.3.5 [#2328](https://github.com/internetee/registry/pull/2328) +* Puma update to 5.6.4 [#2327](https://github.com/internetee/registry/pull/2327) + +31.03.2022 +* Sidekiq update to 6.4.1 [#2322](https://github.com/internetee/registry/pull/2322) + +25.03.2022 +* Bulk change of business contacts' names requires now user confirmation [#2309](https://github.com/internetee/registry/pull/2309) + +23.02.2022 +* FD notes are updated when basis for FD changes [#2216](https://github.com/internetee/registry/issues/2216) +* Admin: date filter end date in domain hostory is now inclusive [#2274](https://github.com/internetee/registry/issues/2274) +* Job for finding and removing disputed statuses from the domains that should not have it [#2281](https://github.com/internetee/registry/issues/2281) + 09.02.2022 * DNSSEC key validation [#1897](https://github.com/internetee/registry/issues/1897) diff --git a/Gemfile b/Gemfile index b5ae07f77..c907eb267 100644 --- a/Gemfile +++ b/Gemfile @@ -17,9 +17,9 @@ gem 'figaro', '~> 1.2' # model related gem 'paper_trail', '~> 12.1' -gem 'pg', '1.3.2' +gem 'pg', '1.3.5' # 1.8 is for Rails < 5.0 -gem 'ransack', '~> 2.5.0' +gem 'ransack', '~> 2.6.0' gem 'truemail', '~> 2.4' # validates email by regexp, mail server existence and address existence gem 'validates_email_format_of', '1.6.3' # validates email against RFC 2822 and RFC 3696 @@ -40,7 +40,7 @@ gem 'select2-rails', '4.0.13' # for autocomplete gem 'selectize-rails', '0.12.6' # include selectize.js for select # registry specfic -gem 'data_migrate', '~> 7.0' +gem 'data_migrate', '~> 8.0' gem 'dnsruby', '~> 1.61' gem 'isikukood' # for EE-id validation gem 'money-rails' @@ -70,7 +70,7 @@ gem 'jquery-ui-rails', '6.0.1' gem 'pdfkit' gem 'que' gem 'que-web' -gem 'sidekiq' +gem 'sidekiq', '>= 6.4.1' gem 'company_register', github: 'internetee/company_register', branch: 'master' diff --git a/Gemfile.lock b/Gemfile.lock index 5eaba3a62..033c9a88b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -193,7 +193,7 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - concurrent-ruby (1.1.9) + concurrent-ruby (1.1.10) connection_pool (2.2.5) countries (4.0.1) i18n_data (~> 0.13.0) @@ -205,7 +205,7 @@ GEM daemons-rails (1.2.1) daemons multi_json (~> 1.0) - data_migrate (7.0.2) + data_migrate (8.0.0) activerecord (>= 5.0) railties (>= 5.0) database_cleaner (2.0.1) @@ -258,7 +258,7 @@ GEM httpi (2.4.5) rack socksify - i18n (1.8.11) + i18n (1.10.0) concurrent-ruby (~> 1.0) i18n_data (0.13.0) isikukood (0.1.2) @@ -289,7 +289,7 @@ GEM kaminari-core (1.2.1) libxml-ruby (3.2.1) logger (1.4.3) - loofah (2.12.0) + loofah (2.16.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -303,7 +303,7 @@ GEM nokogiri (~> 1) rake mini_mime (1.1.1) - mini_portile2 (2.7.1) + mini_portile2 (2.8.0) minitest (5.15.0) monetize (1.9.4) money (~> 6.12) @@ -324,10 +324,10 @@ GEM newrelic_rpm (= 8.1.0) newrelic_rpm (8.1.0) nio4r (2.5.8) - nokogiri (1.13.0) - mini_portile2 (~> 2.7.0) + nokogiri (1.13.4) + mini_portile2 (~> 2.8.0) racc (~> 1.4) - nokogiri (1.13.0-x86_64-linux) + nokogiri (1.13.4-x86_64-linux) racc (~> 1.4) nori (2.6.0) omniauth (1.9.1) @@ -351,7 +351,7 @@ GEM activerecord (>= 5.2) request_store (~> 1.1) pdfkit (0.8.5) - pg (1.3.2) + pg (1.3.5) pg_query (2.1.2) google-protobuf (>= 3.17.1) pghero (2.8.1) @@ -360,7 +360,7 @@ GEM coderay (~> 1.1) method_source (~> 1.0) public_suffix (4.0.6) - puma (5.6.2) + puma (5.6.4) nio4r (~> 2.0) que (0.14.3) que-web (0.7.2) @@ -406,9 +406,9 @@ GEM rake (>= 0.13) thor (~> 1.0) rake (13.0.6) - ransack (2.5.0) - activerecord (>= 5.2.4) - activesupport (>= 5.2.4) + ransack (2.6.0) + activerecord (>= 6.0.4) + activesupport (>= 6.0.4) i18n rbtree3 (0.6.0) redis (4.6.0) @@ -449,7 +449,7 @@ GEM selenium-webdriver (3.142.7) childprocess (>= 0.5, < 4.0) rubyzip (>= 1.2.2) - sidekiq (6.4.0) + sidekiq (6.4.1) connection_pool (>= 2.2.2) rack (~> 2.0) redis (>= 4.2.0) @@ -480,7 +480,7 @@ GEM attr_required (>= 0.0.5) httpclient (>= 2.4) temple (0.8.2) - thor (1.1.0) + thor (1.2.1) tilt (2.0.10) truemail (2.4.9) simpleidn (~> 0.2.1) @@ -524,7 +524,7 @@ GEM wkhtmltopdf-binary (0.12.5.4) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.5.2) + zeitwerk (2.5.4) PLATFORMS ruby @@ -544,7 +544,7 @@ DEPENDENCIES company_register! countries daemons-rails (= 1.2.1) - data_migrate (~> 7.0) + data_migrate (~> 8.0) database_cleaner devise (~> 4.8) digidoc_client! @@ -574,7 +574,7 @@ DEPENDENCIES omniauth-tara! paper_trail (~> 12.1) pdfkit - pg (= 1.3.2) + pg (= 1.3.5) pg_query (>= 0.9.0) pghero pry (= 0.14.1) @@ -582,13 +582,13 @@ DEPENDENCIES que que-web rails (~> 6.1.4) - ransack (~> 2.5.0) + ransack (~> 2.6.0) rest-client rexml sass-rails select2-rails (= 4.0.13) selectize-rails (= 0.12.6) - sidekiq + sidekiq (>= 6.4.1) simplecov (= 0.17.1) simpleidn (= 0.2.1) spy @@ -601,4 +601,4 @@ DEPENDENCIES wkhtmltopdf-binary (~> 0.12.5.1) BUNDLED WITH - 2.2.31 + 2.3.9 diff --git a/README.md b/README.md index d0766bd15..2d5b058cc 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Documentation ------------- * [EPP documentation](/doc/epp) -* [EPP request-response examples](/doc/epp-examples.md) +* [EPP request-response examples](/doc/epp_examples.md) * [REPP documentation](https://internetee.github.io/repp-apidoc/) Installation diff --git a/app/assets/stylesheets/registrant-manifest.sass b/app/assets/stylesheets/registrant-manifest.sass deleted file mode 100644 index 6d0a281fe..000000000 --- a/app/assets/stylesheets/registrant-manifest.sass +++ /dev/null @@ -1,11 +0,0 @@ -//= require 'registrant/registrant-bootstrap' -//= require 'jquery-ui/datepicker' -//= require 'select2' -//= require 'select2-bootstrap' -@import shared/fonts -@import shared/general -@import forms -@import typeaheadjs -@import selectize -@import selectize.bootstrap3 -@import registrant/registrant diff --git a/app/assets/stylesheets/registrant/registrant-bootstrap.sass b/app/assets/stylesheets/registrant/registrant-bootstrap.sass deleted file mode 100644 index 08f6eb984..000000000 --- a/app/assets/stylesheets/registrant/registrant-bootstrap.sass +++ /dev/null @@ -1,19 +0,0 @@ -$brand-primary: #7EA82F -$navbar-default-bg: #7EA82F -$navbar-default-brand-color: #fff -$navbar-default-link-color: #fff -$border-radius-base: 2px -$body-bg: #F8F8F8 -$container-large-desktop: 1040px -$font-family-sans-serif: 'EtelkaLightProRegular', Arial, Helvetica, sans-serif -$font-family-serif: 'EtelkaLightProBold', Georgia, "Times New Roman", Times, serif -$font-size-h1: 26px -$navbar-default-link-active-color: #333 - -@import 'bootstrap-sprockets' -@import 'bootstrap' -@import 'shared/general-bootstrap' - -// Support rails error element -.field_with_errors - @extend .has-error diff --git a/app/assets/stylesheets/registrant/registrant.sass b/app/assets/stylesheets/registrant/registrant.sass deleted file mode 100644 index ebe9f4974..000000000 --- a/app/assets/stylesheets/registrant/registrant.sass +++ /dev/null @@ -1,44 +0,0 @@ -html - position: relative - min-height: 100% - overflow-y: scroll - -body - padding-bottom: 130px - -body > .container - height: 100% - background: #fff - padding: 60px 30px 30px 30px - -h1, h2, h3, h4 - margin-bottom: 0px !important - -// Commented out, default 20px is needed on forms -// hr - // margin-top: 10px !important - // margin-bottom: 10px !important - -.navbar li - font-weight: bold - -.footer - position: absolute - bottom: 0 - width: 100% - height: 130px - background: image_url('bg.jpg') - color: white !important - background-size: 100% - -.confirmation - padding: 40px 0 20px 0 - .column-keys - text-align: right - width: 49% - float: left - .column-values - float: right - font-weight: bold - text-align: left - width: 49% diff --git a/app/controllers/admin/account_activities_controller.rb b/app/controllers/admin/account_activities_controller.rb index ebd44e28e..452acaee1 100644 --- a/app/controllers/admin/account_activities_controller.rb +++ b/app/controllers/admin/account_activities_controller.rb @@ -35,7 +35,8 @@ module Admin respond_to do |format| format.html format.csv do - send_data @q.result.to_csv, filename: "account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv" + raw_csv = CsvGenerator.generate_csv(@q.result) + send_data raw_csv, filename: "account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv" end end diff --git a/app/controllers/admin/auctions_controller.rb b/app/controllers/admin/auctions_controller.rb new file mode 100644 index 000000000..c1023b705 --- /dev/null +++ b/app/controllers/admin/auctions_controller.rb @@ -0,0 +1,142 @@ +module Admin + class AuctionsController < BaseController + load_and_authorize_resource + + def index + params[:q] ||= {} + + @auctions = Auction.with_domain_name(params[:domain_matches]) + .with_status(params[:statuses_contains]) + .with_start_created_at_date(params[:created_at_start]) + .with_end_created_at_date(params[:created_at_end]) + .order(created_at: :desc) + + @auction = Auction.new + + normalize_search_parameters do + @q = @auctions.ransack(PartialSearchFormatter.format(params[:q])) + @auctions = @q.result.page(params[:page]) + end + + @auctions = @auctions.per(params[:results_per_page_auction]) if params[:results_per_page_auction].to_i.positive? + + domains = ReservedDomain.all.order(:name) + q = domains.ransack(PartialSearchFormatter.format(params[:q])) + @domains = q.result.page(params[:page]) + @domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i.positive? + + render_by_format('admin/auctions/index', 'auctions') + end + + def create + auction = Auction.new(domain: params[:domain], status: Auction.statuses[:started], platform: 'manual') + + if domain_exists_in_blocked_disputed_and_registered?(params[:domain]) + flash[:alert] = "Adding #{params[:domain]} failed - domain registered or regsitration is blocked" + redirect_to admin_auctions_path and return + end + + result = check_availability(params[:domain])[0] + if result[:avail].zero? + flash[:alert] = "Cannot generate domain. Reason: #{result[:reason]}" + redirect_to admin_auctions_path and return + end + + if auction.save + reserved_domain = auction.domain if remove_from_reserved(auction) + flash[:notice] = "Auction #{params[:domain]} created. + #{reserved_domain.present? ? 'These domain will be removed from reserved list: ' + reserved_domain : ' '}" + else + flash[:alert] = 'Something goes wrong' + end + + redirect_to admin_auctions_path + end + + def upload_spreadsheet + if params[:q].nil? + flash[:alert] = 'No file upload! Look at the left of upload button!' + redirect_to admin_auctions_path and return + end + + filename = params[:q][:file] + table = CSV.parse(File.read(filename), headers: true) + + failed_names = [] + reserved_domains = [] + + if validate_table(table) + table.each do |row| + record = row.to_h + + if domain_exists_in_blocked_disputed_and_registered?(record['name']) + failed_names << record['name'] + + next + end + + result = check_availability(record['name'])[0] + if result[:avail].zero? + failed_names << record['name'] + + next + end + + auction = Auction.new(domain: record['name'], status: Auction.statuses[:started], platform: 'manual') + flag = remove_from_reserved(auction) if auction.save! + reserved_domains << auction.domain if flag + end + + message_template = "Domains added! + #{reserved_domains.present? ? + 'These domains will be removed from reserved list: ' + reserved_domains.join(' ') + '! ' + : '! '} + #{failed_names.present? ? 'These domains were ignored: ' + failed_names.join(' ') : '!'}" + + flash[:notice] = message_template + else + flash[:alert] = "Invalid CSV format. Should be column with 'name' where is the list of name of domains!" + end + + redirect_to admin_auctions_path + end + + private + + def check_availability(domain_name) + Epp::Domain.check_availability(domain_name) + end + + def domain_exists_in_blocked_disputed_and_registered?(domain_name) + Domain.exists?(name: domain_name) || + BlockedDomain.exists?(name: domain_name) || + Dispute.exists?(domain_name: domain_name) || + Auction.exists?(domain: domain_name) + end + + def validate_table(table) + first_row = table.headers + first_row.include? 'name' + end + + def remove_from_reserved(auction) + domain = ReservedDomain.find_by(name: auction.domain) + + domain.destroy if domain.present? + end + + def normalize_search_parameters + ca_cache = params[:q][:valid_to_lteq] + begin + end_time = params[:q][:valid_to_lteq].try(:to_date) + params[:q][:valid_to_lteq] = end_time.try(:end_of_day) + rescue + logger.warn('Invalid date') + end + + yield + + params[:q][:valid_to_lteq] = ca_cache + end + end +end diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index 016c0a750..56806ba3e 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -26,7 +26,7 @@ module Admin respond_to do |format| format.html { render page } format.csv do - raw_csv = @q.result.to_csv + raw_csv = CsvGenerator.generate_csv(@q.result) send_data raw_csv, filename: "#{filename}_#{Time.zone.now.to_formatted_s(:number)}.csv", type: "#{Mime[:csv]}; charset=utf-8" diff --git a/app/controllers/admin/blocked_domains_controller.rb b/app/controllers/admin/blocked_domains_controller.rb index 268eaca73..c039c5de1 100644 --- a/app/controllers/admin/blocked_domains_controller.rb +++ b/app/controllers/admin/blocked_domains_controller.rb @@ -5,7 +5,7 @@ module Admin def index params[:q] ||= {} domains = BlockedDomain.all.order(:name) - @q = domains.ransack(params[:q]) + @q = domains.ransack(PartialSearchFormatter.format(params[:q])) @domains = @q.result.page(params[:page]) @domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i.positive? @@ -13,13 +13,10 @@ module Admin end def new - @domain = BlockedDomain.new - end def create - @domain = BlockedDomain.new(blocked_domain_params) if @domain.save @@ -29,18 +26,16 @@ module Admin flash.now[:alert] = I18n.t('failed_to_add_domain') render 'new' end - end def delete - if BlockedDomain.find(params[:id]).destroy flash[:notice] = I18n.t('domain_deleted') - redirect_to admin_blocked_domains_path else flash.now[:alert] = I18n.t('failed_to_delete_domain') - redirect_to admin_blocked_domains_path end + + redirect_to admin_blocked_domains_path end def blocked_domain_params diff --git a/app/controllers/admin/contact_versions_controller.rb b/app/controllers/admin/contact_versions_controller.rb index 8ded131c0..43d43d5e8 100644 --- a/app/controllers/admin/contact_versions_controller.rb +++ b/app/controllers/admin/contact_versions_controller.rb @@ -1,29 +1,15 @@ module Admin class ContactVersionsController < BaseController - include ObjectVersionsHelper + include ApplicationHelper load_and_authorize_resource class: Version::ContactVersion def index params[:q] ||= {} - search_params = params[:q].deep_dup.except(:created_at_gteq, :created_at_lteq) - - where_s = '1=1' - - search_params.each do |key, value| - next if value.empty? - - where_s += case key - when 'event' - " AND event = '#{value}'" - else - create_where_string(key, value) - end - end - - versions = Version::ContactVersion.includes(:item).where(where_s).order(created_at: :desc, id: :desc) - @q = versions.ransack(params[:q]) + search_params = PartialSearchFormatter.format(fix_date_params) + versions = Version::ContactVersion.includes(:item).order(created_at: :desc, id: :desc) + @q = versions.ransack(polymorphic_association(search_params)) @versions = @q.result.page(params[:page]) @versions = @versions.per(params[:results_per_page]) if params[:results_per_page].to_i.positive? @@ -53,8 +39,23 @@ module Admin render json: Version::ContactVersion.search_by_query(params[:q]) end - def create_where_string(key, value) - " AND object->>'#{key}' ~* '#{value}'" + private + + def polymorphic_association(search_params) + record_type = {} + fields = %w[name code ident] + fields.each { |field| record_type[:"item_of_Contact_type_#{field}_matches"] = search_params[:"#{field}_matches"] } + + record_type + end + + def fix_date_params + params_copy = params[:q].deep_dup + if params_copy['created_at_lteq'].present? + params_copy['created_at_lteq'] = Date.parse(params_copy['created_at_lteq']) + 1.day + end + + params_copy end end end diff --git a/app/controllers/admin/contacts_controller.rb b/app/controllers/admin/contacts_controller.rb index 192b86242..73ead7b25 100644 --- a/app/controllers/admin/contacts_controller.rb +++ b/app/controllers/admin/contacts_controller.rb @@ -9,10 +9,8 @@ module Admin params[:q] ||= {} search_params = params[:q].deep_dup - if search_params[:domain_contacts_type_in].is_a?(Array) && - search_params[:domain_contacts_type_in].delete('registrant') - search_params[:registrant_domains_id_not_null] = 1 - end + search_params[:registrant_domains_id_not_null] = 1 if search_params[:domain_contacts_type_in].is_a?(Array) && + search_params[:domain_contacts_type_in].delete('registrant') contacts = Contact.includes(:registrar).joins(:registrar) .select('contacts.*, registrars.name as registrars_name') @@ -20,7 +18,7 @@ module Admin contacts = filter_by_flags(contacts) normalize_search_parameters do - @q = contacts.ransack(search_params) + @q = contacts.ransack(PartialSearchFormatter.format(search_params)) @contacts = @q.result.distinct.page(params[:page]) end @@ -33,7 +31,7 @@ module Admin if params[:only_no_country_code].eql?('1') contacts = contacts.where("ident_country_code is null or ident_country_code=''") end - contacts = contacts.email_verification_failed if params[:email_verification_failed].eql?('1') + contacts end @@ -41,8 +39,7 @@ module Admin render json: Contact.search_by_query(params[:q]) end - def edit - end + def edit; end def update cp = ignore_empty_statuses diff --git a/app/controllers/admin/domain_versions_controller.rb b/app/controllers/admin/domain_versions_controller.rb index bdff4b085..c82347ff9 100644 --- a/app/controllers/admin/domain_versions_controller.rb +++ b/app/controllers/admin/domain_versions_controller.rb @@ -1,7 +1,5 @@ module Admin class DomainVersionsController < BaseController - include ObjectVersionsHelper - load_and_authorize_resource class: Version::DomainVersion def index @@ -44,7 +42,7 @@ module Admin where_s += ' AND 1=0' if registrars == [] versions = Version::DomainVersion.includes(:item).where(where_s).order(created_at: :desc, id: :desc) - @q = versions.ransack(params[:q]) + @q = versions.ransack(fix_date_params) @versions = @q.result.page(params[:page]) @versions = @versions.per(params[:results_per_page]) if params[:results_per_page].to_i.positive? @@ -77,5 +75,15 @@ module Admin def create_where_string(key, value) " AND object->>'#{key}' ~* '#{value}'" end + + private + + def fix_date_params + params_copy = params[:q].deep_dup + created_at = params_copy['created_at_lteq'] + params_copy['created_at_lteq'] = Date.parse(created_at) + 1.day if created_at.present? + + params_copy + end end end diff --git a/app/controllers/admin/domains_controller.rb b/app/controllers/admin/domains_controller.rb index 20f47da02..707b40654 100644 --- a/app/controllers/admin/domains_controller.rb +++ b/app/controllers/admin/domains_controller.rb @@ -17,18 +17,10 @@ module Admin end normalize_search_parameters do - @q = domains.ransack(params[:q]) + @q = domains.ransack(PartialSearchFormatter.format(params[:q])) @domains = @q.result.page(params[:page]) - (redirect_to [:admin, @domains.first] and return if @domains.count == 1 && params[:q][:name_matches].present?) - if @domains.count.zero? && params[:q][:name_matches] !~ /^%.+%$/ - # if we do not get any results, add wildcards to the name field and search again - n_cache = params[:q][:name_matches] - params[:q][:name_matches] = "%#{params[:q][:name_matches]}%" - @q = domains.ransack(params[:q]) - @domains = @q.result.page(params[:page]) - params[:q][:name_matches] = n_cache # we don't want to show wildcards in search form - end end + @domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i.positive? render_by_format('admin/domains/index', 'domains') @@ -95,7 +87,7 @@ module Admin def build_associations @server_statuses = @domain.statuses.select { |x| DomainStatus::SERVER_STATUSES.include?(x) } @server_statuses = [nil] if @server_statuses.empty? - @other_statuses = @domain.statuses.select { |x| !DomainStatus::SERVER_STATUSES.include?(x) } + @other_statuses = @domain.statuses.reject { |x| DomainStatus::SERVER_STATUSES.include?(x) } end def ignore_empty_statuses diff --git a/app/controllers/admin/epp_logs_controller.rb b/app/controllers/admin/epp_logs_controller.rb index 279ff1ab8..021c90379 100644 --- a/app/controllers/admin/epp_logs_controller.rb +++ b/app/controllers/admin/epp_logs_controller.rb @@ -5,7 +5,7 @@ module Admin # rubocop:disable Metrics/MethodLength def index - @q = ApiLog::EppLog.ransack(params[:q]) + @q = ApiLog::EppLog.ransack(PartialSearchFormatter.format(params[:q])) @q.sorts = 'id desc' if @q.sorts.empty? @epp_logs = @q.result @@ -29,16 +29,19 @@ module Admin def set_default_dates params[:q] ||= {} + return unless default_dates? - if params[:q][:created_at_gteq].nil? && params[:q][:created_at_lteq].nil? && params[:created_after].present? - default_date = params[:created_after] + default_date = params[:created_after] + default_date = 'today' unless %w[today tomorrow yesterday].include?(default_date) - if !['today', 'tomorrow', 'yesterday'].include?(default_date) - default_date = 'today' - end + params[:q][:created_at_gteq] = Date.send(default_date).strftime("%Y-%m-%d") + end - params[:q][:created_at_gteq] = Date.send(default_date).strftime("%Y-%m-%d") - end + private + + def default_dates? + params[:q] ||= {} + params[:q][:created_at_gteq].nil? && params[:q][:created_at_lteq].nil? && params[:created_after].present? end end end diff --git a/app/controllers/admin/invoices_controller.rb b/app/controllers/admin/invoices_controller.rb index 68db492d8..223257605 100644 --- a/app/controllers/admin/invoices_controller.rb +++ b/app/controllers/admin/invoices_controller.rb @@ -7,8 +7,8 @@ module Admin end def create - r = Registrar.find_by(id: deposit_params[:registrar_id]) - @deposit = Deposit.new(deposit_params.merge(registrar: r)) + registrar = Registrar.find(deposit_params[:registrar_id]) + @deposit = Deposit.new(deposit_params.merge(registrar: registrar)) @invoice = @deposit.issue_prepayment_invoice if @invoice&.persisted? diff --git a/app/controllers/admin/repp_logs_controller.rb b/app/controllers/admin/repp_logs_controller.rb index 028dbffc8..abb8415bc 100644 --- a/app/controllers/admin/repp_logs_controller.rb +++ b/app/controllers/admin/repp_logs_controller.rb @@ -5,7 +5,7 @@ module Admin # rubocop:disable Metrics/MethodLength def index - @q = ApiLog::ReppLog.ransack(params[:q]) + @q = ApiLog::ReppLog.ransack(PartialSearchFormatter.format(params[:q])) @q.sorts = 'id desc' if @q.sorts.empty? @repp_logs = @q.result @@ -31,17 +31,19 @@ module Admin def set_default_dates params[:q] ||= {} + return unless default_dates? - if params[:q][:created_at_gteq].nil? && params[:q][:created_at_lteq].nil? && params[:created_after].present? + default_date = params[:created_after] + default_date = 'today' unless %w[today tomorrow yesterday].include?(default_date) - default_date = params[:created_after] + params[:q][:created_at_gteq] = Date.send(default_date).strftime("%Y-%m-%d") + end - if !['today', 'tomorrow', 'yesterday'].include?(default_date) - default_date = 'today' - end + private - params[:q][:created_at_gteq] = Date.send(default_date).strftime("%Y-%m-%d") - end + def default_dates? + params[:q] ||= {} + params[:q][:created_at_gteq].nil? && params[:q][:created_at_lteq].nil? && params[:created_after].present? end end end diff --git a/app/controllers/admin/reserved_domains_controller.rb b/app/controllers/admin/reserved_domains_controller.rb index 35a81842d..20957dec4 100644 --- a/app/controllers/admin/reserved_domains_controller.rb +++ b/app/controllers/admin/reserved_domains_controller.rb @@ -6,7 +6,7 @@ module Admin def index params[:q] ||= {} domains = ReservedDomain.all.order(:name) - @q = domains.ransack(params[:q]) + @q = domains.ransack(PartialSearchFormatter.format(params[:q])) @domains = @q.result.page(params[:page]) @domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i.positive? @@ -17,11 +17,9 @@ module Admin @domain = ReservedDomain.new end - def edit - end + def edit; end def create - @domain = ReservedDomain.new(reserved_domain_params) if @domain.save @@ -31,34 +29,48 @@ module Admin flash.now[:alert] = I18n.t('failed_to_add_domain') render 'new' end - end def update - if @domain.update(reserved_domain_params) flash[:notice] = I18n.t('domain_updated') else flash.now[:alert] = I18n.t('failed_to_update_domain') end - render 'edit' + render 'edit' end def delete - if ReservedDomain.find(params[:id]).destroy flash[:notice] = I18n.t('domain_deleted') - redirect_to admin_reserved_domains_path else flash.now[:alert] = I18n.t('failed_to_delete_domain') - redirect_to admin_reserved_domains_path end + redirect_to admin_reserved_domains_path + end + + def release_to_auction + redirect_to admin_reserved_domains_path and return if params[:reserved_elements].nil? + + reserved_domains_ids = params[:reserved_elements][:domain_ids] + reserved_domains = ReservedDomain.where(id: reserved_domains_ids) + + reserved_domains.each do |domain| + Auction.create!(domain: domain.name, status: Auction.statuses[:started], platform: 'manual') + domain.destroy! + end + + redirect_to admin_auctions_path end private + def reserved_checked_elements + # params.require(:reserved_elements).permit(:name, :password) + end + def reserved_domain_params params.require(:reserved_domain).permit(:name, :password) end diff --git a/app/controllers/api/v1/auctions_controller.rb b/app/controllers/api/v1/auctions_controller.rb index de8e94442..9a01f4e68 100644 --- a/app/controllers/api/v1/auctions_controller.rb +++ b/app/controllers/api/v1/auctions_controller.rb @@ -44,7 +44,7 @@ module Api private def serializable_hash(auction) - { id: auction.uuid, domain: auction.domain, status: auction.status } + { id: auction.uuid, domain: auction.domain, status: auction.status, platform: auction.platform } end def serializable_hash_for_update_action(auction) diff --git a/app/controllers/api/v1/registrant/contacts_controller.rb b/app/controllers/api/v1/registrant/contacts_controller.rb index 30096ab8a..b196c567a 100644 --- a/app/controllers/api/v1/registrant/contacts_controller.rb +++ b/app/controllers/api/v1/registrant/contacts_controller.rb @@ -34,6 +34,17 @@ module Api end end + def do_need_update_contacts + result = current_registrant_user.do_need_update_contacts? + render json: { update_contacts: result[:result], counter: result[:counter] } + end + + def update_contacts + contacts = current_registrant_user.update_contacts + + render json: { message: 'get it', contacts: contacts } + end + def update logger.debug 'Received update request' logger.debug params diff --git a/app/controllers/registrant_controller.rb b/app/controllers/registrant_controller.rb deleted file mode 100644 index 1e97281e7..000000000 --- a/app/controllers/registrant_controller.rb +++ /dev/null @@ -1,37 +0,0 @@ -class RegistrantController < ApplicationController - before_action :authenticate_registrant_user! - before_action :set_paper_trail_whodunnit - layout 'registrant/application' - - include Registrant::ApplicationHelper - - helper_method :head_title_sufix - - def head_title_sufix - t(:registrant_head_title_sufix) - end - - private - - def current_ability - @current_ability ||= Ability.new(current_registrant_user, request.remote_ip) - end - - def user_for_paper_trail - current_registrant_user.present? ? current_registrant_user.id_role_username : 'anonymous' - end - - def current_user_contacts - current_registrant_user.contacts - rescue CompanyRegister::NotAvailableError - flash.now[:notice] = t('registrant.company_register_unavailable') - current_registrant_user.direct_contacts - end - - def current_user_domains - current_registrant_user.domains - rescue CompanyRegister::NotAvailableError - flash.now[:notice] = t('registrant.company_register_unavailable') - current_registrant_user.direct_domains - end -end diff --git a/app/controllers/registrar/account_activities_controller.rb b/app/controllers/registrar/account_activities_controller.rb index 55e53f8fc..0ad8c3d5a 100644 --- a/app/controllers/registrar/account_activities_controller.rb +++ b/app/controllers/registrar/account_activities_controller.rb @@ -20,7 +20,8 @@ class Registrar respond_to do |format| format.html { @account_activities = @q.result.page(params[:page]) } format.csv do - send_data @q.result.to_csv, filename: "account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv" + raw_csv = CsvGenerator.generate_csv(@q.result) + send_data raw_csv, filename: "account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv" end end diff --git a/app/controllers/registrar/contacts_controller.rb b/app/controllers/registrar/contacts_controller.rb index ec4ce5129..812e278e5 100644 --- a/app/controllers/registrar/contacts_controller.rb +++ b/app/controllers/registrar/contacts_controller.rb @@ -40,7 +40,7 @@ class Registrar @contacts = @contacts.per(contacts_per_page) if contacts_per_page.positive? end format.csv do - raw_csv = contacts.to_csv + raw_csv = CsvGenerator.generate_csv(contacts) send_data raw_csv, filename: 'contacts.csv', type: "#{Mime[:csv]}; charset=utf-8" end format.pdf do diff --git a/app/controllers/registrar/domains_controller.rb b/app/controllers/registrar/domains_controller.rb index e5ab59fa2..3347f5d38 100644 --- a/app/controllers/registrar/domains_controller.rb +++ b/app/controllers/registrar/domains_controller.rb @@ -88,14 +88,16 @@ class Registrar @domain_params[:period] = Depp::Domain.default_period end + # rubocop:disable Metrics/CognitiveComplexity def create authorize! :create, Depp::Domain @domain_params = domain_params.to_h @data = @domain.create(@domain_params) - if response_ok? + if @data && response_ok? redirect_to info_registrar_domains_url(domain_name: @domain_params[:name]) else + flash[:alert] = t('.email_error_message') unless @emails_check_result render 'new' end end @@ -113,13 +115,15 @@ class Registrar @data = @domain.update(@domain_params) @dispute = Dispute.active.find_by(domain_name: @domain_params[:name]) - if response_ok? + if @data && response_ok? redirect_to info_registrar_domains_url(domain_name: @domain_params[:name]) else + flash[:alert] = t('.email_error_message') unless @emails_check_result params[:domain_name] = @domain_params[:name] render 'new' end end + # rubocop:enable Metrics/CognitiveComplexity def delete authorize! :delete, Depp::Domain diff --git a/app/controllers/repp/v1/domains/contacts_controller.rb b/app/controllers/repp/v1/domains/contacts_controller.rb index 4c89243c7..b41b3a378 100644 --- a/app/controllers/repp/v1/domains/contacts_controller.rb +++ b/app/controllers/repp/v1/domains/contacts_controller.rb @@ -14,8 +14,8 @@ module Repp api :GET, '/repp/v1/domains/:domain_name/contacts' desc "View domain's admin and tech contacts" def index - admin_contacts = @domain.admin_domain_contacts.pluck(:contact_code_cache) - tech_contacts = @domain.tech_domain_contacts.pluck(:contact_code_cache) + admin_contacts = @domain.admin_domain_contacts.map(&:contact).pluck(:code) + tech_contacts = @domain.tech_domain_contacts.map(&:contact).pluck(:code) data = { admin_contacts: admin_contacts, tech_contacts: tech_contacts } render_success(data: data) @@ -38,7 +38,6 @@ module Repp def cta(action = 'add') params[:contacts].each { |c| c[:action] = action } action = Actions::DomainUpdate.new(@domain, contact_create_params, false) - # rubocop:disable Style/AndOr handle_errors(@domain) and return unless action.call # rubocop:enable Style/AndOr diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 3de98b88c..122fc40d4 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -10,27 +10,11 @@ module ApplicationHelper end def ident_for(contact) - if contact.is_a? Hash - ident_country_code = contact[:ident_country_code] - ident_type = contact[:ident_type] - ident = contact[:ident] - else - ident_country_code = contact.ident_country_code - ident_type = contact.ident_type - ident = contact.ident - end + ident = contact.ident + description = "[#{contact.ident_country_code} #{contact.ident_type}]" + description.prepend("#{ident} ") if ident.present? - case ident_type - when 'birthday' - "#{ident} [#{ident_country_code} #{ident_type}]" - else - if ident.present? - "#{ident} [#{ident_country_code} #{ident_type}]" - else - "[#{ident_country_code} #{ident_type}]" - end - - end + description end def current_commit_link diff --git a/app/helpers/auction_helper.rb b/app/helpers/auction_helper.rb new file mode 100644 index 000000000..25cf463af --- /dev/null +++ b/app/helpers/auction_helper.rb @@ -0,0 +1,19 @@ +module AuctionHelper + include ActionView::Helpers::TagHelper + + def colorize_auction(auction) + case auction.status + when 'started' then render_status_black(auction.domain) + when 'awaiting_payment' then render_status_black(auction.domain) + else render_status_green(auction.domain) + end + end + + def render_status_black(name) + tag.span name.to_s, style: 'color: black;' + end + + def render_status_green(name) + tag.span name.to_s, style: 'color: green;' + end +end diff --git a/app/helpers/object_versions_helper.rb b/app/helpers/object_versions_helper.rb deleted file mode 100644 index dae357cf6..000000000 --- a/app/helpers/object_versions_helper.rb +++ /dev/null @@ -1,19 +0,0 @@ -module ObjectVersionsHelper - def attach_existing_fields(version, new_object) - version.object_changes.to_h.each do |key, value| - method_name = "#{key}=".to_sym - new_object.public_send(method_name, event_value(version, value)) if new_object.respond_to?(method_name) - end - end - - def only_present_fields(version, model) - field_names = model.column_names - version.object.to_h.select { |key, _value| field_names.include?(key) } - end - - private - - def event_value(version, val) - version.event == 'destroy' ? val.first : val.last - end -end diff --git a/app/helpers/registrant/application_helper.rb b/app/helpers/registrant/application_helper.rb deleted file mode 100644 index 6451f91a2..000000000 --- a/app/helpers/registrant/application_helper.rb +++ /dev/null @@ -1,6 +0,0 @@ -module Registrant::ApplicationHelper - def env_style - return '' if unstable_env.nil? - "background-image: url(#{image_path("registrar/bg-#{unstable_env}.png")});" - end -end diff --git a/app/interactions/actions/contact_create.rb b/app/interactions/actions/contact_create.rb index d31af2e38..f3e6560b8 100644 --- a/app/interactions/actions/contact_create.rb +++ b/app/interactions/actions/contact_create.rb @@ -19,12 +19,12 @@ module Actions def maybe_change_email return if Rails.env.test? - [:regex, :mx].each do |m| + %i[regex mx].each do |m| result = Actions::SimpleMailValidator.run(email: contact.email, level: m) - next if result - contact.add_epp_error('2005', nil, "email didn't pass validation", I18n.t(:parameter_value_syntax_error)) + err_text = "email '#{contact.email}' didn't pass validation" + contact.add_epp_error('2005', nil, nil, "#{I18n.t(:parameter_value_syntax_error)} #{err_text}") @error = true return end @@ -84,6 +84,7 @@ module Actions return false if @error contact.generate_code + contact.email_history = contact.email contact.save end end diff --git a/app/interactions/actions/contact_update.rb b/app/interactions/actions/contact_update.rb index d9a136dd3..bfa3f3b7c 100644 --- a/app/interactions/actions/contact_update.rb +++ b/app/interactions/actions/contact_update.rb @@ -23,11 +23,12 @@ module Actions def maybe_change_email return if Rails.env.test? - [:regex, :mx].each do |m| + %i[regex mx].each do |m| result = Actions::SimpleMailValidator.run(email: @new_attributes[:email], level: m) next if result - contact.add_epp_error('2005', nil, "email didn't pass validation", I18n.t(:parameter_value_syntax_error)) + err_text = "email '#{new_attributes[:email]}' didn't pass validation" + contact.add_epp_error('2005', nil, nil, "#{I18n.t(:parameter_value_syntax_error)} #{err_text}") @error = true return end @@ -36,12 +37,11 @@ module Actions end def maybe_filtering_old_failed_records - if contact.validation_events.count > 1 - contact.validation_events.order!(created_at: :asc) - while contact.validation_events.count >= 1 - contact.validation_events.first.destroy - end - end + validation_events = contact.validation_events + return unless validation_events.count > 1 + + validation_events.order!(created_at: :asc) + validation_events.first.destroy while validation_events.count >= 1 end def maybe_remove_address @@ -112,10 +112,12 @@ module Actions email_changed = contact.will_save_change_to_email? old_email = contact.email_was + contact.email_history = old_email updated = contact.save - if updated && email_changed && contact.registrant? - ContactMailer.email_changed(contact: contact, old_email: old_email).deliver_now + if updated && email_changed + contact.validation_events.where('event_data @> ?', { 'email': old_email }.to_json).destroy_all + ContactMailer.email_changed(contact: contact, old_email: old_email).deliver_now if contact.registrant? end updated diff --git a/app/interactions/actions/domain_create.rb b/app/interactions/actions/domain_create.rb index 8fd25df0f..970d74b3b 100644 --- a/app/interactions/actions/domain_create.rb +++ b/app/interactions/actions/domain_create.rb @@ -120,7 +120,7 @@ module Actions contact = Contact.find_by(code: contact_code) arr = admin ? @admin_contacts : @tech_contacts if contact - arr << { contact_id: contact.id, contact_code_cache: contact.code } + arr << { contact_id: contact.id, contact_code: contact.code } else domain.add_epp_error('2303', 'contact', contact_code, %i[domain_contacts not_found]) end diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb index 40b7876f6..a86b038ff 100644 --- a/app/interactions/actions/domain_update.rb +++ b/app/interactions/actions/domain_update.rb @@ -45,6 +45,10 @@ module Actions def assign_new_registrant domain.add_epp_error('2306', nil, nil, %i[registrant cannot_be_missing]) unless params[:registrant][:code] + contact_code = params[:registrant][:code] + contact = Contact.find_by(code: contact_code) + validate_email(contact.email) + regt = Registrant.find_by(code: params[:registrant][:code]) unless regt domain.add_epp_error('2303', 'registrant', params[:registrant], %i[registrant not_found]) @@ -120,9 +124,35 @@ module Actions @dnskeys << { id: dnkey.id, _destroy: 1 } if dnkey end + def start_validate_email(props) + contact = Contact.find_by(code: props[0][:contact_code]) + + return if contact.nil? + + validate_email(contact.email) + end + + def validate_email(email) + return true if Rails.env.test? + + %i[regex mx].each do |m| + result = Actions::SimpleMailValidator.run(email: email, level: m) + next if result + + err_text = "email #{email} didn't pass validation" + domain.add_epp_error('2005', nil, nil, "#{I18n.t(:parameter_value_syntax_error)} #{err_text}") + @error = true + return + end + + true + end + def assign_admin_contact_changes props = gather_domain_contacts(params[:contacts].select { |c| c[:type] == 'admin' }) + start_validate_email(props) if props.present? + if props.any? && domain.admin_change_prohibited? domain.add_epp_error('2304', 'admin', DomainStatus::SERVER_ADMIN_CHANGE_PROHIBITED, I18n.t(:object_status_prohibits_operation)) @@ -136,6 +166,8 @@ module Actions props = gather_domain_contacts(params[:contacts].select { |c| c[:type] == 'tech' }, admin: false) + start_validate_email(props) if props.present? + if props.any? && domain.tech_change_prohibited? domain.add_epp_error('2304', 'tech', DomainStatus::SERVER_TECH_CHANGE_PROHIBITED, I18n.t(:object_status_prohibits_operation)) @@ -173,7 +205,7 @@ module Actions domain.add_epp_error('2306', 'contact', code, %i[domain_contacts admin_contact_can_be_only_private_person]) else - add ? { contact_id: obj.id, contact_code_cache: obj.code } : { id: obj.id, _destroy: 1 } + add ? { contact_id: obj.id, contact_code: obj.code } : { id: obj.id, _destroy: 1 } end end diff --git a/app/interactions/actions/email_check.rb b/app/interactions/actions/email_check.rb index 248952a47..c16c035ed 100644 --- a/app/interactions/actions/email_check.rb +++ b/app/interactions/actions/email_check.rb @@ -31,31 +31,27 @@ module Actions Rails.env.test? && check_level == 'smtp' ? :mx : check_level.to_sym end + def destroy_old_validations(validation_events, minimum_size, check_level) + return unless validation_events.count > minimum_size && @check_level == check_level + + validation_events.order!(created_at: :asc) + validation_events.first.destroy while validation_events.count > minimum_size + end + def filtering_old_failed_records(result) - if @check_level == "mx" && !result.success && validation_eventable.validation_events.count > 3 - validation_eventable.validation_events.order!(created_at: :asc) - while validation_eventable.validation_events.count > 3 - validation_eventable.validation_events.first.destroy - end - end + events = validation_eventable.validation_events - if @check_level == "mx" && result.success && validation_eventable.validation_events.count > 1 - validation_eventable.validation_events.order!(created_at: :asc) - while validation_eventable.validation_events.count > 1 - validation_eventable.validation_events.first.destroy - end - end + destroy_old_validations(events, ValidationEvent::MX_CHECK, 'mx') unless result.success - if @check_level == "smtp" && validation_eventable.validation_events.count > 1 - validation_eventable.validation_events.order!(created_at: :asc) - while validation_eventable.validation_events.count > 1 - validation_eventable.validation_events.first.destroy - end - end + destroy_old_validations(events, ValidationEvent::REDEEM_EVENTS_COUNT_BY_LEVEL[:mx], 'mx') if result.success + + destroy_old_validations(events, ValidationEvent::REDEEM_EVENTS_COUNT_BY_LEVEL[:smtp], 'smtp') end def save_result(result) - if !result.success && @check_level == "mx" + contacts = Contact.where(email: email) + + if !result.success && @check_level == 'mx' result_validation = Actions::AAndAaaaEmailValidation.call(email: @email, value: 'A') output_a_and_aaaa_validation_results(email: @email, result: result_validation, @@ -65,11 +61,13 @@ module Actions output_a_and_aaaa_validation_results(email: @email, result: result_validation, type: 'AAAA') + result.success = result_validation.present? + end - result_validation.present? ? result.success = true : result.success = false - validation_eventable.validation_events.create(validation_event_attrs(result)) - else - validation_eventable.validation_events.create(validation_event_attrs(result)) + contacts.find_in_batches(batch_size: 500) do |contact_batches| + contact_batches.each do |contact| + contact.validation_events.create(validation_event_attrs(result)) + end end rescue ActiveRecord::RecordNotSaved logger.info "Cannot save validation result for #{log_object_id}" @@ -97,8 +95,7 @@ module Actions when 'AAAA' ress = dns.getresources domain, Resolv::DNS::Resource::IN::AAAA end - - result = ress.map { |r| r.address } + result = ress.map(&:address) end result diff --git a/app/interactions/domains/force_delete/notify_registrar.rb b/app/interactions/domains/force_delete/notify_registrar.rb index e4aa48976..25d59bf29 100644 --- a/app/interactions/domains/force_delete/notify_registrar.rb +++ b/app/interactions/domains/force_delete/notify_registrar.rb @@ -6,18 +6,26 @@ module Domains end def notify_without_email - domain.registrar.notifications.create!(text: I18n.t('force_delete_set_on_domain', - domain_name: domain.name, - outzone_date: domain.outzone_date, - purge_date: domain.purge_date)) + template = I18n.t('force_delete_set_on_domain', + domain_name: domain.name, + outzone_date: domain.outzone_date, + purge_date: domain.purge_date) + + return if domain.registrar.notifications.last.text.include? template + + domain.registrar.notifications.create!(text: template) end def notify_with_email - domain.registrar.notifications.create!(text: I18n.t('force_delete_auto_email', - domain_name: domain.name, - outzone_date: domain.outzone_date, - purge_date: domain.purge_date, - email: email)) + template = I18n.t('force_delete_auto_email', + domain_name: domain.name, + outzone_date: domain.outzone_date, + purge_date: domain.purge_date, + email: email) + + return if domain.registrar.notifications.last.text.include? template + + domain.registrar.notifications.create!(text: template) end end end diff --git a/app/interactions/domains/force_delete_email/base.rb b/app/interactions/domains/force_delete_email/base.rb index f22244045..d75749b50 100644 --- a/app/interactions/domains/force_delete_email/base.rb +++ b/app/interactions/domains/force_delete_email/base.rb @@ -11,6 +11,8 @@ module Domains domains = domain_contacts.map(&:domain).flatten + Domain.where(registrant_id: registrant_ids) + return if expired_or_hold_domains_exists?(domains) + domains.each do |domain| next if domain.expired? @@ -20,6 +22,12 @@ module Domains private + def expired_or_hold_domains_exists?(domains) + domains.any? do |domain| + domain.statuses.include?(DomainStatus::SERVER_HOLD) && email.include?(domain.name) + end + end + def before_execute_force_delete(domain) if domain.force_delete_scheduled? && !domain.status_notes[DomainStatus::FORCE_DELETE].nil? added_additional_email_into_notes(domain) @@ -28,6 +36,18 @@ module Domains end end + def notify_registrar(domain) + template = I18n.t('force_delete_auto_email', + domain_name: domain.name, + outzone_date: domain.outzone_date, + purge_date: domain.purge_date, + email: domain.status_notes[DomainStatus::FORCE_DELETE]) + + return if domain.registrar.notifications.last.text.include? template + + domain.registrar.notifications.create!(text: template) + end + def process_force_delete(domain) domain.schedule_force_delete(type: :soft, notify_by_email: true, @@ -39,6 +59,8 @@ module Domains def added_additional_email_into_notes(domain) return if domain.status_notes[DomainStatus::FORCE_DELETE].include? email + # notify_registrar(domain) + domain.status_notes[DomainStatus::FORCE_DELETE].concat(" #{email}") domain.save(validate: false) end diff --git a/app/jobs/check_force_delete_job.rb b/app/jobs/check_force_delete_job.rb new file mode 100644 index 000000000..5fb3408f1 --- /dev/null +++ b/app/jobs/check_force_delete_job.rb @@ -0,0 +1,43 @@ +class CheckForceDeleteJob < ApplicationJob + def perform(contact_ids) + contacts = Contact.find(contact_ids) + + contacts.each do |contact| + email = contact.email + + if contact.need_to_start_force_delete? + Domains::ForceDeleteEmail::Base.run(email: email) + elsif contact.need_to_lift_force_delete? + domain_list(email).each { |domain| refresh_status_notes(contact, domain) } + end + end + end + + private + + def refresh_status_notes(contact, domain) + force_delete_emails = domain.status_notes[DomainStatus::FORCE_DELETE] + return unless force_delete_emails + + force_delete_emails.slice!(contact.email_history) + force_delete_emails.lstrip! + domain.save(validate: false) + + notify_registrar(domain) unless force_delete_emails.empty? + end + + def domain_list(email) + domain_contacts = Contact.where(email: email).map(&:domain_contacts).flatten + registrant_ids = Registrant.where(email: email).pluck(:id) + + (domain_contacts.map(&:domain).flatten + Domain.where(registrant_id: registrant_ids)).uniq + end + + def notify_registrar(domain) + domain.registrar.notifications.create!(text: I18n.t('force_delete_auto_email', + domain_name: domain.name, + outzone_date: domain.outzone_date, + purge_date: domain.purge_date, + email: domain.status_notes[DomainStatus::FORCE_DELETE])) + end +end diff --git a/app/jobs/dispute_status_update_job.rb b/app/jobs/dispute_status_update_job.rb index 5e42f29e1..3051b0ce3 100644 --- a/app/jobs/dispute_status_update_job.rb +++ b/app/jobs/dispute_status_update_job.rb @@ -1,6 +1,7 @@ class DisputeStatusUpdateJob < ApplicationJob - def perform(logger: Logger.new($stdout)) + def perform(logger: Logger.new($stdout), include_closed: false) @logger = logger + @include_closed = include_closed @backlog = { 'activated': 0, 'closed': 0, 'activate_fail': [], 'close_fail': [] } .with_indifferent_access @@ -15,7 +16,11 @@ class DisputeStatusUpdateJob < ApplicationJob end def close_disputes - disputes = Dispute.where(closed: nil).where('expires_at < ?', Time.zone.today).all + disputes = if @include_closed + Dispute.where('expires_at < ?', Time.zone.today).all + else + Dispute.where(closed: nil).where('expires_at < ?', Time.zone.today).all + end @logger.info "DisputeStatusUpdateJob - Found #{disputes.count} closable disputes" disputes.each do |dispute| process_dispute(dispute, closing: true) diff --git a/app/jobs/migrate_before_force_delete_statuses_job.rb b/app/jobs/migrate_before_force_delete_statuses_job.rb deleted file mode 100644 index 7e6a1e1c0..000000000 --- a/app/jobs/migrate_before_force_delete_statuses_job.rb +++ /dev/null @@ -1,36 +0,0 @@ -class MigrateBeforeForceDeleteStatusesJob < ApplicationJob - def perform - logger.info 'Ran MigrateBeforeForceDeleteStatusesJob!' - - domains = Domain.where.not(statuses_before_force_delete: nil) - logger.info "Total domains are #{domains.count}" - - interate_domain_in_batches(domains) - end - - private - - def interate_domain_in_batches(domains) - count = 0 - - domains.find_in_batches do |domain_batches| - count += domain_batches.count - logger.info "Proccesing #{count} domains of #{domains.count}" - domain_batches.each do |domain| - migrate_data_to_statuses_history(domain) - end - end - end - - def migrate_data_to_statuses_history(domain) - domain.update(force_delete_domain_statuses_history: domain.statuses_before_force_delete) - rescue StandardError => e - logger.warn "#{domain.name} crashed!" - logger.warn e.to_s - raise e - end - - def logger - @logger ||= Logger.new(Rails.root.join('log/migrate_before_force_delete_statuses.log')) - end -end diff --git a/app/jobs/migrate_statuses_to_domain_history_job.rb b/app/jobs/migrate_statuses_to_domain_history_job.rb deleted file mode 100644 index f35c986b6..000000000 --- a/app/jobs/migrate_statuses_to_domain_history_job.rb +++ /dev/null @@ -1,36 +0,0 @@ -class MigrateStatusesToDomainHistoryJob < ApplicationJob - def perform - logger.info 'Ran MigrateStatusesToDomainHistoryJob!' - - domains = Domain.where(locked_by_registrant_at: nil) - logger.info "Total domains are #{domains.count}" - - interate_domain_in_batches(domains) - end - - private - - def interate_domain_in_batches(domains) - count = 0 - - domains.find_in_batches do |domain_batches| - count += domain_batches.count - logger.info "Proccesing #{count} domains of #{domains.count}" - domain_batches.each do |domain| - migrate_data_to_admin_store_field(domain) - end - end - end - - def migrate_data_to_admin_store_field(domain) - domain.update(admin_store_statuses_history: domain.statuses) - rescue StandardError => e - logger.warn "#{domain.name} crashed!" - logger.warn e.to_s - raise e - end - - def logger - @logger ||= Logger.new(Rails.root.join('log/migrate_statuses_to_domain_history.log')) - end -end diff --git a/app/jobs/nameserver_record_validation_job.rb b/app/jobs/nameserver_record_validation_job.rb index 7dd2211a4..f737c0f36 100644 --- a/app/jobs/nameserver_record_validation_job.rb +++ b/app/jobs/nameserver_record_validation_job.rb @@ -64,12 +64,11 @@ class NameserverRecordValidationJob < ApplicationJob nameserver.save end - def add_nameserver_to_failed(nameserver:, reason:) - if nameserver.validation_counter.nil? - nameserver.validation_counter = 1 - else - nameserver.validation_counter = nameserver.validation_counter + 1 - end + def add_nameserver_to_failed(nameserver:, reason:, result_reason:) + return cname_case_handle(nameserver: nameserver, reason: reason) if result_reason == 'cname' + + nameserver.validation_counter = 1 if nameserver.validation_counter.nil? + nameserver.validation_counter = nameserver.validation_counter + 1 nameserver.failed_validation_reason = reason nameserver.save @@ -77,15 +76,25 @@ class NameserverRecordValidationJob < ApplicationJob failed_log(text: reason, nameserver: nameserver, domain: nameserver.domain) if nameserver.failed_validation? end + def cname_case_handle(nameserver:, reason:) + nameserver.validation_datetime = Time.zone.now + nameserver.failed_validation_reason = reason + nameserver.save + + failed_log(text: reason, nameserver: nameserver, domain: nameserver.domain) + end + def parse_result(result, nameserver) domain = Domain.find(nameserver.domain_id) - text = "" + text = '' case result[:reason] when 'answer' - text = "No any answer comes from **#{nameserver.hostname}**. Nameserver not exist" + text = "DNS Server **#{nameserver.hostname}** not responding" when 'serial' - text = "Serial number for nameserver hostname **#{nameserver.hostname}** doesn't present. SOA validation failed." + text = "Serial number for nameserver hostname **#{nameserver.hostname}** of #{nameserver.domain.name} doesn't present in zone. SOA validation failed." + when 'cname' + text = "Warning: SOA record expected but CNAME found instead. This setup can lead to unexpected errors when using the domain: hostname - **#{nameserver.hostname}** of #{nameserver.domain.name}" when 'not found' text = "Seems nameserver hostname **#{nameserver.hostname}** doesn't exist" when 'exception' @@ -97,7 +106,7 @@ class NameserverRecordValidationJob < ApplicationJob end logger.info text - add_nameserver_to_failed(nameserver: nameserver, reason: text) + add_nameserver_to_failed(nameserver: nameserver, reason: text, result_reason: result[:reason]) false end diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb index 623513768..69168efbb 100644 --- a/app/jobs/validate_dnssec_job.rb +++ b/app/jobs/validate_dnssec_job.rb @@ -36,7 +36,7 @@ class ValidateDnssecJob < ApplicationJob domain.nameservers.each do |n| next unless n.validated? - validate(hostname: n.hostname, domain: domain) + validate(nameserver: n, domain: domain) notify_contacts(domain) logger.info "----------------------------" @@ -54,25 +54,26 @@ class ValidateDnssecJob < ApplicationJob # ContactNotification.notify_tech_contact(domain: domain, reason: 'dnssec') end - def validate(hostname:, domain:, type: 'DNSKEY', klass: 'IN') - resolver = prepare_validator(hostname) + def validate(nameserver:, domain:, type: 'DNSKEY', klass: 'IN') + resolver = prepare_validator(nameserver.hostname) answer = resolver.query(domain.name, type, klass) - return logger.info "no any data for #{domain.name} | hostname - #{hostname}" if answer.nil? + return logger.info "no any data for #{domain.name} | hostname - #{nameserver.hostname}" if answer.nil? logger.info "-----------" - logger.info "data for domain name - #{domain.name} | hostname - #{hostname}" + logger.info "data for domain name - #{domain.name} | hostname - #{nameserver.hostname}" logger.info "-----------" response_container = parse_response(answer) - compare_dnssec_data(response_container: response_container, domain: domain) + compare_dnssec_data(response_container: response_container, domain: domain, nameserver: nameserver) rescue Exception => e - logger.error "#{e.message} - domain name: #{domain.name} - hostname: #{hostname}" + logger.error "#{e.message} - domain name: #{domain.name} - hostname: #{nameserver.hostname}" + nameserver.update(failed_validation_reason: "#{e.message} - domain name: #{domain.name} - hostname: #{nameserver.hostname}") nil end - def compare_dnssec_data(response_container:, domain:) + def compare_dnssec_data(response_container:, domain:, nameserver:) domain.dnskeys.each do |key| next unless key.flags.to_s == '257' next if key.validation_datetime.present? @@ -82,11 +83,15 @@ class ValidateDnssecJob < ApplicationJob if flag key.validation_datetime = Time.zone.now + key.failed_validation_reason = nil key.save + nameserver.failed_validation_reason = nil + nameserver.save logger.info text + " ------->> succesfully!" else - logger.info text + " ------->> not found in zone!" + key.update!(failed_validation_reason: text + " not found in zone! Domain name - #{domain.name}. Hostname - #{nameserver.hostname}") + logger.info text + " ------->> not found in zone! Domain name - #{domain.name}. Hostname - #{nameserver.hostname}" end end end @@ -133,10 +138,11 @@ class ValidateDnssecJob < ApplicationJob inner_resolver.nameserver = nameserver inner_resolver.packet_timeout = timeouts.to_i inner_resolver.query_timeout = timeouts.to_i - resolver = Dnsruby::Recursor.new(inner_resolver) - resolver.dnssec = true + # resolver = Dnsruby::Recursor.new(inner_resolver) + # resolver.dnssec = true - resolver + # resolver + inner_resolver end def logger diff --git a/app/jobs/verify_emails_job.rb b/app/jobs/verify_emails_job.rb index 4b9b98fb7..7274fcad4 100644 --- a/app/jobs/verify_emails_job.rb +++ b/app/jobs/verify_emails_job.rb @@ -1,8 +1,13 @@ class VerifyEmailsJob < ApplicationJob discard_on StandardError - def perform(contact:, check_level: 'mx') - contact_not_found(contact.id) unless contact + def perform(email:, check_level: 'mx') + contact = Contact.find_by(email: email) + + return Rails.logger.info "No found #{email} contact" if contact.nil? + + return unless filter_check_level(contact) + validate_check_level(check_level) action = Actions::EmailCheck.new(email: contact.email, validation_eventable: contact, @@ -32,4 +37,17 @@ class VerifyEmailsJob < ApplicationJob def valid_check_levels ValidationEvent::VALID_CHECK_LEVELS end + + def get_validation_results(contact) + ValidationEvent.where(created_at: Time.zone.now.beginning_of_day..Time.zone.now.end_of_day) + end + + def filter_check_level(contact) + return true unless contact.validation_events.exists? + + data = contact.validation_events.order(created_at: :asc).last + return true if data.successful? && data.created_at < (Time.zone.now - ValidationEvent::VALIDATION_PERIOD) + + !(data.failed? && data.event_data['check_level'] == 'regex') + end end diff --git a/app/lib/to_csv.rb b/app/lib/to_csv.rb deleted file mode 100644 index 32c288978..000000000 --- a/app/lib/to_csv.rb +++ /dev/null @@ -1,10 +0,0 @@ -module ToCsv - def to_csv - CSV.generate do |csv| - csv << column_names - all.find_each do |item| - csv << item.attributes.values_at(*column_names) - end - end - end -end diff --git a/app/models/ability.rb b/app/models/ability.rb index baa26e4cb..bc2caa6ba 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -12,7 +12,7 @@ class Ability @user.roles&.each { |role| send(role) } when 'ApiUser' @user.roles&.each { |role| send(role) } - when 'RegistrantUser' + when 'RegistrantUser' static_registrant end @@ -95,6 +95,7 @@ class Ability can :manage, User can :manage, ApiUser can :manage, AdminUser + can :manage, Auction can :manage, Certificate can :manage, LegalDocument can :manage, BankStatement diff --git a/app/models/account.rb b/app/models/account.rb index fe0820888..7639c61dd 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -1,5 +1,4 @@ class Account < ApplicationRecord - extend ToCsv include Versions belongs_to :registrar, required: true @@ -12,4 +11,12 @@ class Account < ApplicationRecord def activities account_activities end + + def as_csv_row + [id, balance, currency, registrar] + end + + def self.csv_header + ['Id', 'Balance', 'Currency', 'Registrar'] + end end diff --git a/app/models/account_activity.rb b/app/models/account_activity.rb index 05873a2a6..38fa70358 100644 --- a/app/models/account_activity.rb +++ b/app/models/account_activity.rb @@ -11,6 +11,7 @@ class AccountActivity < ApplicationRecord UPDATE_CREDIT = 'update_credit'.freeze after_create :update_balance + def update_balance account.balance += sum account.save @@ -19,23 +20,17 @@ class AccountActivity < ApplicationRecord save end + def as_csv_row + [account.registrar.try(:code), description, I18n.t(activity_type), I18n.l(created_at), sum] + end + class << self def types_for_select [CREATE, RENEW, ADD_CREDIT, UPDATE_CREDIT].map { |x| [I18n.t(x), x] } end - def to_csv - attributes = %w(description activity_type created_at sum) - - CSV.generate(headers: true) do |csv| - csv << %w(registrar description activity_type receipt_date sum) - - all.each do |x| - attrs = [x.account.registrar.try(:code)] - attrs += attributes.map { |attr| x.send(attr) } - csv << attrs - end - end + def csv_header + ['Registrar', 'Description', 'Activity Type', 'Receipt Date', 'Sum'] end end end diff --git a/app/models/action.rb b/app/models/action.rb index ac5ee7f72..8a822f867 100644 --- a/app/models/action.rb +++ b/app/models/action.rb @@ -2,18 +2,40 @@ class Action < ApplicationRecord has_paper_trail versions: { class_name: 'Version::ActionVersion' } belongs_to :user - belongs_to :contact + belongs_to :contact, optional: true + has_many :subactions, class_name: 'Action', + foreign_key: 'bulk_action_id', + inverse_of: :bulk_action, + dependent: :destroy + belongs_to :bulk_action, class_name: 'Action', optional: true validates :operation, inclusion: { in: proc { |action| action.class.valid_operations } } class << self def valid_operations - %w[update] + %w[update bulk_update] end end def notification_key - raise 'Action object is missing' unless contact + raise 'Action object is missing' unless bulk_action? || contact + "contact_#{operation}".to_sym end + + def bulk_action? + !!subactions.exists? + end + + def to_non_available_contact_codes + return [] unless bulk_action? + + subactions.map do |a| + { + code: a.contact.code, + avail: 0, + reason: 'in use', + } + end + end end diff --git a/app/models/api_log/epp_log.rb b/app/models/api_log/epp_log.rb index feed1ecad..c89569be5 100644 --- a/app/models/api_log/epp_log.rb +++ b/app/models/api_log/epp_log.rb @@ -1,5 +1,3 @@ module ApiLog - class EppLog < Db - extend ToCsv - end + class EppLog < Db; end end diff --git a/app/models/api_log/repp_log.rb b/app/models/api_log/repp_log.rb index 62dcee238..540a9043a 100644 --- a/app/models/api_log/repp_log.rb +++ b/app/models/api_log/repp_log.rb @@ -1,5 +1,3 @@ module ApiLog - class ReppLog < Db - extend ToCsv - end + class ReppLog < Db; end end diff --git a/app/models/auction.rb b/app/models/auction.rb index 791184d60..465a827ec 100644 --- a/app/models/auction.rb +++ b/app/models/auction.rb @@ -9,11 +9,30 @@ class Auction < ApplicationRecord domain_not_registered: 'domain_not_registered', } + enum platform: %i[auto manual] + PENDING_STATUSES = [statuses[:started], statuses[:awaiting_payment], statuses[:payment_received]].freeze + private_constant :PENDING_STATUSES + scope :with_status, ->(status) { + where(status: status) if status.present? + } + + scope :with_start_created_at_date, ->(start_created_at) { + where('created_at >= ?', start_created_at) if start_created_at.present? + } + + scope :with_end_created_at_date, ->(end_created_at) { + where('created_at <= ?', end_created_at) if end_created_at.present? + } + + scope :with_domain_name, ->(domain_name) { + where('domain ilike ?', "%#{domain_name.strip}%") if domain_name.present? + } + def self.pending(domain_name) find_by(domain: domain_name.to_s, status: PENDING_STATUSES) end diff --git a/app/models/blocked_domain.rb b/app/models/blocked_domain.rb index fb50a8b52..f82faa771 100644 --- a/app/models/blocked_domain.rb +++ b/app/models/blocked_domain.rb @@ -1,6 +1,5 @@ class BlockedDomain < ApplicationRecord include Versions - extend ToCsv before_save :generate_data after_destroy :remove_data diff --git a/app/models/bulk_action.rb b/app/models/bulk_action.rb new file mode 100644 index 000000000..9c98ee2db --- /dev/null +++ b/app/models/bulk_action.rb @@ -0,0 +1 @@ +class BulkAction < Action; end diff --git a/app/models/concerns/contact/disclosable.rb b/app/models/concerns/contact/disclosable.rb deleted file mode 100644 index a61b240b1..000000000 --- a/app/models/concerns/contact/disclosable.rb +++ /dev/null @@ -1,22 +0,0 @@ -module Contact::Disclosable - extend ActiveSupport::Concern - - class_methods do - attr_accessor :disclosable_attributes - end - - included do - self.disclosable_attributes = %w[name email] - validate :validate_disclosed_attributes - end - - private - - def validate_disclosed_attributes - return if disclosed_attributes.empty? - - has_undisclosable_attributes = (disclosed_attributes - self.class.disclosable_attributes) - .any? - errors.add(:disclosed_attributes, :invalid) if has_undisclosable_attributes - end -end diff --git a/app/models/concerns/domain/force_delete.rb b/app/models/concerns/domain/force_delete.rb index 3fa3bf627..7dd309c41 100644 --- a/app/models/concerns/domain/force_delete.rb +++ b/app/models/concerns/domain/force_delete.rb @@ -34,13 +34,7 @@ module Domain::ForceDelete reason = explicit&.downcase return reason if %w[invalid_email invalid_phone].include?(reason) - if contact_emails_verification_failed.present? - 'invalid_email' - elsif registrant.org? - 'legal_person' - else - 'private_person' - end + registrant.org? ? 'legal_person' : 'private_person' end def force_delete_scheduled? diff --git a/app/models/concerns/email_verifable.rb b/app/models/concerns/email_verifable.rb index 4f9b4ffeb..be9603031 100644 --- a/app/models/concerns/email_verifable.rb +++ b/app/models/concerns/email_verifable.rb @@ -5,10 +5,6 @@ module EmailVerifable scope :recently_not_validated, -> { where.not(id: ValidationEvent.validated_ids_by(name)) } end - def email_verification_failed? - need_to_start_force_delete? - end - def validate_email_data(level:, count:) validation_events.order(created_at: :desc).limit(count).all? do |event| event.check_level == level.to_s && event.failed? @@ -18,9 +14,7 @@ module EmailVerifable def need_to_start_force_delete? flag = false ValidationEvent::INVALID_EVENTS_COUNT_BY_LEVEL.each do |level, count| - if validation_events.count >= count && validate_email_data(level: level, count: count) - flag = true - end + flag = true if validation_events.count >= count && validate_email_data(level: level, count: count) end flag diff --git a/app/models/contact.rb b/app/models/contact.rb index 84d4ba962..2be404997 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -7,7 +7,6 @@ class Contact < ApplicationRecord include UserEvents include Contact::Transferable include Contact::Identical - include Contact::Disclosable include Contact::Archivable include EmailVerifable @@ -16,7 +15,7 @@ class Contact < ApplicationRecord has_many :domain_contacts has_many :domains, through: :domain_contacts has_many :legal_documents, as: :documentable - has_many :validation_events, as: :validation_eventable + has_many :validation_events, as: :validation_eventable, dependent: :destroy has_many :registrant_domains, class_name: 'Domain', foreign_key: 'registrant_id' has_many :actions, dependent: :destroy @@ -25,10 +24,18 @@ class Contact < ApplicationRecord alias_attribute :kind, :ident_type alias_attribute :copy_from_id, :original_id # Old attribute name; for PaperTrail - scope :email_verification_failed, lambda { - joins('LEFT JOIN email_address_verifications emv ON contacts.email = emv.email') - .where('success = false and verified_at IS NOT NULL') - } + scope :with_different_company_name, (lambda do |company| + where("ident = ? AND ident_country_code = 'EE' AND name != ?", + company.registration_number, + company.company_name) + end) + + scope :with_different_registrant_name, (lambda do |user| + where('ident = ? AND ident_country_code = ? AND UPPER(name) != UPPER(?)', + user.ident, + user.country.alpha2, + user.username) + end) NAME_REGEXP = /([\u00A1-\u00B3\u00B5-\u00BF\u0021-\u0026\u0028-\u002C\u003A-\u0040]| [\u005B-\u005F\u007B-\u007E\u2040-\u206F\u20A0-\u20BF\u2100-\u218F])/x @@ -42,7 +49,7 @@ class Contact < ApplicationRecord validates :phone, presence: true, e164: true, phone: true - validate :correct_email_format, if: proc { |c| c.will_save_change_to_email? } + # validate :correct_email_format, if: proc { |c| c.will_save_change_to_email? } validates :code, uniqueness: { message: :epp_id_taken }, @@ -188,15 +195,6 @@ class Contact < ApplicationRecord ] end - def to_csv - CSV.generate do |csv| - csv << column_names - all.each do |contact| - csv << contact.attributes.values_at(*column_names) - end - end - end - def pdf(html) kit = PDFKit.new(html) kit.to_pdf @@ -569,4 +567,27 @@ class Contact < ApplicationRecord def deletable? !linked? end + + def ident_human_description + description = "[#{ident_country_code} #{ident_type}]" + description.prepend("#{ident} ") if ident.present? + + description + end + + def as_csv_row + [ + name, + code, + ident_human_description, + email, + created_at.to_formatted_s(:db), + registrar, + phone, + ] + end + + def self.csv_header + ['Name', 'ID', 'Ident', 'E-mail', 'Created at', 'Registrar', 'Phone'] + end end diff --git a/app/models/depp/contact.rb b/app/models/depp/contact.rb index 48e49d5e4..7007bcd00 100644 --- a/app/models/depp/contact.rb +++ b/app/models/depp/contact.rb @@ -5,7 +5,8 @@ module Depp attr_accessor :id, :name, :email, :phone, :org_name, :ident, :ident_type, :ident_country_code, :street, :city, :zip, :state, :country_code, - :password, :legal_document, :statuses, :code + :password, :legal_document, :statuses, :code, + :email_history DISABLED = 'Disabled' DISCLOSURE_TYPES = [DISABLED, '1', '0'] diff --git a/app/models/dispute.rb b/app/models/dispute.rb index cbf93566a..f5a948355 100644 --- a/app/models/dispute.rb +++ b/app/models/dispute.rb @@ -1,5 +1,4 @@ class Dispute < ApplicationRecord - extend ToCsv include WhoisStatusPopulate validates :domain_name, :password, :starts_at, :expires_at, presence: true before_validation :fill_empty_passwords, :set_expiry_date diff --git a/app/models/dns/domain_name.rb b/app/models/dns/domain_name.rb index bceb4433b..6c68c3797 100644 --- a/app/models/dns/domain_name.rb +++ b/app/models/dns/domain_name.rb @@ -35,6 +35,7 @@ module DNS def sell_at_auction auction = Auction.new auction.domain = name + auction.platform = 'auto' auction.start ToStdout.msg "Created the auction: #{auction.inspect}" update_whois_from_auction(auction) diff --git a/app/models/domain.rb b/app/models/domain.rb index 873216cf1..68c5bc611 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -161,14 +161,6 @@ class Domain < ApplicationRecord attribute: 'hostname' } - validates :tech_domain_contacts, uniqueness_multi: { - attribute: 'contact_code_cache' - } - - validates :admin_domain_contacts, uniqueness_multi: { - attribute: 'contact_code_cache' - } - validates :dnskeys, uniqueness_multi: { attribute: 'public_key' } @@ -289,21 +281,6 @@ class Domain < ApplicationRecord ) end - def to_csv - CSV.generate do |csv| - headers = column_names.dup - swap_elements(headers, [[0, 1], [1, 5]]) - headers[0] = 'Domain' - headers[1] = headers[1].humanize - csv << headers - all.find_each do |item| - row = item.attributes.values_at(*column_names) - swap_elements(row, [[0, 1], [1, 5]]) - csv << row - end - end - end - private def registrant_user_domains_by_registrant(registrant_user) @@ -749,8 +726,36 @@ class Domain < ApplicationRecord DNS::DomainName.new(name) end - def contact_emails_verification_failed - contacts.select(&:email_verification_failed?)&.map(&:email)&.uniq + def as_csv_row + [ + name, + registrant_name, + valid_to.to_formatted_s(:db), + registrar, + created_at.to_formatted_s(:db), + statuses, + contacts.pluck(:code), + force_delete_date, + force_delete_data, + ] + end + + def registrant_name + return registrant.name if registrant + + ver = Version::ContactVersion.where(item_id: registrant_id).last + contact = Contact.all_versions_for([registrant_id], created_at).first + + contact = ObjectVersionsParser.new(ver).parse if contact.nil? && ver + + contact.try(:name) || 'Deleted' + end + + def self.csv_header + [ + 'Domain', 'Registrant', 'Valid to', 'Registrar', 'Created at', + 'Statuses', 'Contacts code', 'Force delete date', 'Force delete data' + ] end def self.pdf(html) diff --git a/app/models/domain_contact.rb b/app/models/domain_contact.rb index 910f4e445..4a791493f 100644 --- a/app/models/domain_contact.rb +++ b/app/models/domain_contact.rb @@ -6,32 +6,21 @@ class DomainContact < ApplicationRecord belongs_to :contact belongs_to :domain + validates :contact, presence: true + + after_destroy :update_contact attr_accessor :value_typeahead + attr_writer :contact_code self.ignored_columns = %w[legacy_domain_id legacy_contact_id] - def epp_code_map - { - '2302' => [ - [:contact_code_cache, :taken, { value: { obj: 'contact', val: contact_code_cache } }] - ] - } - end - def name return 'Tech' if type == 'TechDomainContact' return 'Admin' if type == 'AdminDomainContact' + '' end - validates :contact, presence: true - - before_save :update_contact_code_cache - def update_contact_code_cache - self.contact_code_cache = contact.code - end - - after_destroy :update_contact def update_contact Contact.find(contact_id).save end diff --git a/app/models/epp/contact.rb b/app/models/epp/contact.rb index 614be201b..35691d789 100644 --- a/app/models/epp/contact.rb +++ b/app/models/epp/contact.rb @@ -47,7 +47,7 @@ class Epp::Contact < Contact codes = codes.map { |c| c.include?(':') ? c : "#{reg}:#{c}" } res = [] - codes.map { |c| c.include?(':') ? c : "#{reg}:#{c}" }.map { |c| c.strip.upcase }.each do |x| + codes.map { |c| c.strip.upcase }.each do |x| c = find_by_epp_code(x) res << (c ? { code: c.code, avail: 0, reason: 'in use' } : { code: x, avail: 1 }) end diff --git a/app/models/invoice.rb b/app/models/invoice.rb index df8b7aff8..6ba3a158d 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -3,7 +3,6 @@ class Invoice < ApplicationRecord include Invoice::Cancellable include Invoice::Payable include Invoice::BookKeeping - extend ToCsv belongs_to :buyer, class_name: 'Registrar' has_one :account_activity @@ -117,6 +116,23 @@ class Invoice < ApplicationRecord e_invoice_sent_at.present? end + def as_csv_row + [ + number, + buyer, + cancelled? ? I18n.t(:cancelled) : due_date, + receipt_date_status, + issue_date, + total, + currency, + seller_name, + ] + end + + def self.csv_header + ['Number', 'Buyer', 'Due Date', 'Receipt Date', 'Issue Date', 'Total', 'Currency', 'Seller Name'] + end + def self.create_from_transaction!(transaction) registrar_user = Registrar.find_by(reference_no: transaction.parsed_ref_number) return unless registrar_user @@ -128,6 +144,16 @@ class Invoice < ApplicationRecord private + def receipt_date_status + if paid? + receipt_date + elsif cancelled? + I18n.t(:cancelled) + else + I18n.t(:unpaid) + end + end + def apply_default_buyer_vat_no self.buyer_vat_no = buyer.vat_no end diff --git a/app/models/notification.rb b/app/models/notification.rb index 07e824367..c9af66c56 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -2,7 +2,7 @@ class Notification < ApplicationRecord include Versions # version/notification_version.rb belongs_to :registrar - belongs_to :action + belongs_to :action, optional: true scope :unread, -> { where(read: false) } diff --git a/app/models/registrant_user.rb b/app/models/registrant_user.rb index 5fe508125..073ab3214 100644 --- a/app/models/registrant_user.rb +++ b/app/models/registrant_user.rb @@ -20,49 +20,45 @@ class RegistrantUser < User def companies(company_register = CompanyRegister::Client.new) return [] if ident.include?('-') - companies = company_register.representation_rights(citizen_personal_code: ident, - citizen_country_code: country.alpha3) - - companies = update_contacts_before_receive(companies) - companies + company_register.representation_rights(citizen_personal_code: ident, + citizen_country_code: country.alpha3) rescue CompanyRegister::NotAvailableError - return [] + [] end - def update_contacts_before_receive(companies) - return [] if companies.blank? + def do_need_update_contacts? + counter = 0 + + counter += Contact.with_different_registrant_name(self).size companies.each do |company| - contacts = Contact.where(ident: company.registration_number, ident_country_code: 'EE') - - next if contacts.blank? - - contacts.each do |contact| - next if company.company_name == contact.name - - update_company_name(contact: contact, company: company) - end + counter += Contact.with_different_company_name(company).size end - companies + return { result: true, counter: counter } if counter.positive? + + { result: false, counter: 0 } end - def update_company_name(contact:, company:) - old_contact_name = contact.name - contact.name = company.company_name + # rubocop:disable Metrics/MethodLength + def update_contacts + user = self + contacts = [] + contacts.concat(Contact.with_different_registrant_name(user).each do |c| + c.write_attribute(:name, user.username) + end) + companies.each do |company| + contacts.concat(Contact.with_different_company_name(company).each do |c| + c.write_attribute(:name, company.company_name) + end) + end - contact.save(validate: false) + return [] if contacts.blank? - notify_registrar_data_updated(company_name: company.company_name, - old_contact_name: old_contact_name, - contact: contact) - end - - def notify_registrar_data_updated(company_name:, old_contact_name:, contact:) - contact.registrar.notifications.create!( - text: "Contact update: #{contact.id} name updated from #{old_contact_name} to #{company_name} by the registry" - ) + group_and_bulk_update(contacts) + contacts end + # rubocop:enable Metrics/MethodLength def contacts(representable: true) Contact.registrant_user_contacts(self, representable: representable) @@ -100,17 +96,6 @@ class RegistrantUser < User username.split.second end - def update_related_contacts - contacts = Contact.where(ident: ident, ident_country_code: country.alpha2) - .where('UPPER(name) != UPPER(?)', username) - - contacts.each do |contact| - contact.update(name: username) - action = actions.create!(contact: contact, operation: :update) - contact.registrar.notify(action) - end - end - class << self def find_or_create_by_api_data(user_data = {}) return false unless user_data[:ident] @@ -147,9 +132,27 @@ class RegistrantUser < User user = find_or_create_by(registrant_ident: "#{user_data[:country_code]}-#{user_data[:ident]}") user.username = "#{user_data[:first_name]} #{user_data[:last_name]}" user.save - - user.update_related_contacts user end end + + private + + def group_and_bulk_update(contacts) + contacts.group_by(&:registrar_id).each do |registrar_id, reg_contacts| + bulk_action, action = actions.create!(operation: :bulk_update) if reg_contacts.size > 1 + reg_contacts.each do |c| + if c.save(validate: false) + action = actions.create!(contact: c, operation: :update, bulk_action_id: bulk_action&.id) + end + end + notify_registrar_contacts_updated(action: bulk_action || action, + registrar_id: registrar_id) + end + end + + def notify_registrar_contacts_updated(action:, registrar_id:) + registrar = Registrar.find(registrar_id) + registrar&.notify(action) + end end diff --git a/app/models/registrar.rb b/app/models/registrar.rb index 8517bd6fe..aafc391cd 100644 --- a/app/models/registrar.rb +++ b/app/models/registrar.rb @@ -34,8 +34,8 @@ class Registrar < ApplicationRecord attribute :vat_rate, ::Type::VatRate.new after_initialize :set_defaults - validate :correct_email_format, if: proc { |c| c.will_save_change_to_email? } - validate :correct_billing_email_format + # validate :correct_email_format, if: proc { |c| c.will_save_change_to_email? } + # validate :correct_billing_email_format alias_attribute :contact_email, :email @@ -218,8 +218,15 @@ class Registrar < ApplicationRecord end def notify(action) - text = I18n.t("notifications.texts.#{action.notification_key}", contact: action.contact.code) - notifications.create!(text: text) + text = I18n.t("notifications.texts.#{action.notification_key}", contact: action.contact&.code, + count: action.subactions&.count) + if action.bulk_action? + notifications.create!(text: text, action_id: action.id, + attached_obj_type: 'BulkAction', + attached_obj_id: action.id) + else + notifications.create!(text: text) + end end def e_invoice_iban diff --git a/app/models/reserved_domain.rb b/app/models/reserved_domain.rb index 5d585e5d9..10d5edd11 100644 --- a/app/models/reserved_domain.rb +++ b/app/models/reserved_domain.rb @@ -1,5 +1,4 @@ class ReservedDomain < ApplicationRecord - extend ToCsv include Versions # version/reserved_domain_version.rb include WhoisStatusPopulate before_save :fill_empty_passwords diff --git a/app/models/validation_event.rb b/app/models/validation_event.rb index 69fd660e5..3e7670fac 100644 --- a/app/models/validation_event.rb +++ b/app/models/validation_event.rb @@ -35,8 +35,6 @@ class ValidationEvent < ApplicationRecord scope :smtp, -> { where('event_data @> ?', { 'check_level': 'smtp' }.to_json) } scope :by_object, ->(object) { where(validation_eventable: object) } - after_create :check_for_force_delete - def self.validated_ids_by(klass) old_records .successful @@ -59,28 +57,4 @@ class ValidationEvent < ApplicationRecord def object validation_eventable end - - def check_for_force_delete - if object.need_to_start_force_delete? - start_force_delete - elsif object.need_to_lift_force_delete? - lift_force_delete - end - end - - def start_force_delete - Domains::ForceDeleteEmail::Base.run(email: email) - end - - def lift_force_delete - # domain_contacts = Contact.where(email: email).map(&:domain_contacts).flatten - # registrant_ids = Registrant.where(email: email).pluck(:id) - # - # domains = domain_contacts.map(&:domain).flatten + - # Domain.where(registrant_id: registrant_ids) - # - # domains.each do |domain| - # Domains::ForceDeleteLift::Base.run(domain: domain) - # end - end end diff --git a/app/models/version/contact_version.rb b/app/models/version/contact_version.rb index 95bd4b677..d3ff1130c 100644 --- a/app/models/version/contact_version.rb +++ b/app/models/version/contact_version.rb @@ -1,7 +1,23 @@ class Version::ContactVersion < PaperTrail::Version - extend ToCsv include VersionSession self.table_name = :log_contacts self.sequence_name = :log_contacts_id_seq + + def as_csv_row + contact = ObjectVersionsParser.new(self).parse + + [ + contact.name, + contact.code, + contact.ident_human_description, + contact.registrar, + event, + created_at.to_formatted_s(:db) + ] + end + + def self.csv_header + ['Name', 'ID', 'Ident', 'Registrar', 'Action', 'Created at'] + end end diff --git a/app/models/version/domain_version.rb b/app/models/version/domain_version.rb index 2c6848d4b..e84fc9da2 100644 --- a/app/models/version/domain_version.rb +++ b/app/models/version/domain_version.rb @@ -1,5 +1,4 @@ class Version::DomainVersion < PaperTrail::Version - extend ToCsv include VersionSession self.table_name = :log_domains @@ -7,6 +6,18 @@ class Version::DomainVersion < PaperTrail::Version scope :deleted, -> { where(event: 'destroy') } + def as_csv_row + domain = ObjectVersionsParser.new(self).parse + + [ + domain.name, + domain.registrant_name, + domain.registrar, + event, + created_at.to_formatted_s(:db) + ] + end + def self.was_contact_linked?(contact_id) sql = <<-SQL SELECT @@ -43,4 +54,8 @@ class Version::DomainVersion < PaperTrail::Version count_by_sql(sql).nonzero? end + + def self.csv_header + ['Name', 'Registrant', 'Registrar', 'Action', 'Created at'] + end end diff --git a/app/presenters/domain_presenter.rb b/app/presenters/domain_presenter.rb index 812881742..f19bbb62f 100644 --- a/app/presenters/domain_presenter.rb +++ b/app/presenters/domain_presenter.rb @@ -52,10 +52,6 @@ class DomainPresenter end end - def contact_emails_verification_failed - domain.contact_emails_verification_failed.join(', ') - end - def remove_registry_lock_btn return unless domain.locked_by_registrant? diff --git a/app/services/csv_generator.rb b/app/services/csv_generator.rb new file mode 100644 index 000000000..d92beeddc --- /dev/null +++ b/app/services/csv_generator.rb @@ -0,0 +1,29 @@ +class CsvGenerator + class << self + def generate_csv(objects) + class_name = objects.first.class + return default_generation(objects) unless custom_csv?(class_name) + + CSV.generate do |csv| + csv << class_name.csv_header + objects.each { |object| csv << object.as_csv_row } + end + end + + private + + def default_generation(objects) + CSV.generate do |csv| + csv << objects.column_names + objects.all.find_each { |object| csv << object.attributes.values_at(*objects.column_names) } + end + end + + def custom_csv?(class_name) + [ + Version::DomainVersion, Version::ContactVersion, Domain, + Contact, Invoice, Account, AccountActivity + ].include?(class_name) + end + end +end diff --git a/app/services/nameserver_validator.rb b/app/services/nameserver_validator.rb index c45003cd3..6436ba363 100644 --- a/app/services/nameserver_validator.rb +++ b/app/services/nameserver_validator.rb @@ -35,8 +35,14 @@ module NameserverValidator return { result: false, reason: 'answer' } if result.answer.empty? + decision = result.answer.any? do |a| + a.type == 'CNAME' + end + + return { result: false, reason: 'cname' } if decision + decision = result.answer.all? do |a| - a.serial.present? + a.instance_variable_defined? '@serial' end return { result: false, reason: 'serial' } unless decision diff --git a/app/services/object_versions_parser.rb b/app/services/object_versions_parser.rb new file mode 100644 index 000000000..5871a6bd6 --- /dev/null +++ b/app/services/object_versions_parser.rb @@ -0,0 +1,28 @@ +class ObjectVersionsParser + def initialize(version) + @version = version + end + + def parse + model = @version.item_type.constantize + attributes = only_present_fields(model) + history_object = model.new(attributes) + attach_existing_fields(history_object) unless @version.event == 'destroy' + + history_object + end + + private + + def attach_existing_fields(history_object) + @version.object_changes.to_h.each do |key, value| + method_name = "#{key}=".to_sym + history_object.public_send(method_name, value.last) if history_object.respond_to?(method_name) + end + end + + def only_present_fields(model) + field_names = model.column_names + @version.object.to_h.select { |key, _value| field_names.include?(key) } + end +end diff --git a/app/services/partial_search_formatter.rb b/app/services/partial_search_formatter.rb new file mode 100644 index 000000000..af0c7978d --- /dev/null +++ b/app/services/partial_search_formatter.rb @@ -0,0 +1,13 @@ +class PartialSearchFormatter + def self.format(params) + search_params = params.deep_dup + + search_params.each do |key, value| + next unless key.include?('matches') && value.present? + + value << '%' + end + + search_params + end +end diff --git a/app/views/admin/auctions/_modal.html.erb b/app/views/admin/auctions/_modal.html.erb new file mode 100644 index 000000000..e57d2139d --- /dev/null +++ b/app/views/admin/auctions/_modal.html.erb @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/app/views/admin/auctions/index.html.erb b/app/views/admin/auctions/index.html.erb new file mode 100644 index 000000000..85d533fa7 --- /dev/null +++ b/app/views/admin/auctions/index.html.erb @@ -0,0 +1,155 @@ + + +
+
+ <%= form_with url: admin_auctions_path, method: :get, html: { style: 'margin-bottom: 0;', class: 'js-form', autocomplete: 'off' } do |f| %> +
+
+
+ <%= f.label :domain %> + <%= f.search_field :domain_matches, value: params[:domain_matches], class: 'form-control', placeholder: t(:name) %> +
+
+ <%= f.label :status %> + <%= select_tag :statuses_contains, options_for_select(Auction.statuses.map { |x| [x[0], x[1]] }, params[:q][:status]), { include_blank:true, class: 'form-control' } %> +
+
+
+
+ <%= f.label t(:created_at_from) %> + <%= f.search_field :created_at_start, value: params[:created_at_start], class: 'form-control js-datepicker', placeholder: t(:created_at_from) %> +
+
+
+
+ <%= f.label t(:created_at_until) %> + <%= f.search_field :created_at_end, value: params[:created_at_end], class: 'form-control js-datepicker', placeholder: t(:created_at_until) %> +
+
+
+
+ <%= label_tag t(:results_per_page) %> + <%= text_field_tag :results_per_page_auction, params[:results_per_page_auction], class: 'form-control', placeholder: t(:results_per_page) %> +
+
+
+ +
+ <%= link_to('Clear', admin_auctions_path, class: 'btn btn-default') %> +
+
+ <%= link_to 'Download auction list', admin_auctions_path(format: :csv, params: params.permit!), + "data-toggle" => "tooltip", "data-placement" => "bottom", "title" => 'Download CSV', + class: 'btn btn-primary' %> +
+
+ <%= link_to "#", class: "btn btn-warning edit", id: 'reserved-modal', + data: { + toggle: "modal", + url: admin_reserved_domains_path, + target: "#user-form-edit"} do %> + + Get reserved domains + <% end %> + + <%= render 'modal' %> + +
+
+
+ <% end %> +
+
+ +
+ + <%= search_form_for [:admin, @q], method: :post, html: { style: 'margin-bottom: 0;', class: 'js-form', autocomplete: 'off' } do |f| %> + <%= label_tag :new_auction %> + +
+ <%= text_field_tag :domain, params[:domain], class: 'form-control', placeholder: 'domain name' %> + <%= f.submit 'Create', class: 'btn btn-primary', style: 'margin-left: .4rem;', id: 'new-auction-btn' %> +
+ <% end %> + +
+ +
+
+ <%= search_form_for @q, url: upload_spreadsheet_admin_auctions_path, method: :post, html: { style: 'margin-bottom: 0; display: flex; flex-direction: row; align-items: center;', class: 'js-form', autocomplete: 'off' } do |f| %> + <%= f.file_field :file, + accept: ".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel", + direct_upload: true, + style: 'width: 200px;' %> + <%= f.submit 'Upload csv', class: 'btn btn-primary' %> + <% end %> + +
+
+ +
+
+
+ + + + + + + + + + + + + + <% @auctions.each do |auction| %> + + + + + + + + + <% end %> + +
+ <%= sort_link(@q, 'domain') %> + + <%= sort_link(@q, 'status') %> + + <%= sort_link(@q, 'created_at') %> + + <%= sort_link(@q, 'registration_code') %> + + <%= sort_link(@q, 'registration_deadline') %> + + <%= sort_link(@q, 'platform', 'Type') %> +
<%= colorize_auction(auction) %><%= auction.status %><%= auction.created_at %><%= auction.registration_code %><%= auction.registration_deadline %><%= auction.platform.nil? ? 'auto' : auction.platform %>
+
+
+
+ +
+
+ <%= paginate @auctions %> +
+
+ +
+
+ + \ No newline at end of file diff --git a/app/views/admin/base/_menu.haml b/app/views/admin/base/_menu.haml index c5edd4708..92efc2347 100644 --- a/app/views/admin/base/_menu.haml +++ b/app/views/admin/base/_menu.haml @@ -31,6 +31,7 @@ %li.dropdown-header= t(:system) %li= link_to t('.settings'), admin_settings_path %li= link_to t('.zones'), admin_zones_path + %li= link_to t(:auctions), admin_auctions_path %li= link_to t('.blocked_domains'), admin_blocked_domains_path %li= link_to t('.reserved_domains'), admin_reserved_domains_path %li= link_to t('.disputed_domains'), admin_disputes_path diff --git a/app/views/admin/contact_versions/index.haml b/app/views/admin/contact_versions/index.haml index 4d7a9948d..e181673f2 100644 --- a/app/views/admin/contact_versions/index.haml +++ b/app/views/admin/contact_versions/index.haml @@ -7,15 +7,15 @@ .col-md-3 .form-group = f.label :name - = f.search_field :name, value: params[:q][:name], class: 'form-control', placeholder: t(:name) + = f.search_field :name_matches, value: params[:q][:name_matches], class: 'form-control', placeholder: t(:name) .col-md-3 .form-group = f.label :id - = f.search_field :code, value: params[:q][:code], class: 'form-control', placeholder: t(:id) + = f.search_field :code_matches, value: params[:q][:code_matches], class: 'form-control', placeholder: t(:id) .col-md-3 .form-group = f.label :ident - = f.search_field :ident, value: params[:q][:ident], class: 'form-control', placeholder: t(:ident) + = f.search_field :ident_matches, value: params[:q][:ident_matches], class: 'form-control', placeholder: t(:ident) .col-md-3 .form-group = label_tag :action @@ -64,9 +64,7 @@ %tbody - @versions.each do |version| - if version - - attributes = only_present_fields(version, Contact) - - contact = Contact.new(attributes) - - attach_existing_fields(version, contact) + - contact = ObjectVersionsParser.new(version).parse %tr %td= link_to(contact.name, admin_contact_version_path(version.id)) diff --git a/app/views/admin/contact_versions/show.haml b/app/views/admin/contact_versions/show.haml index 901f5ee1a..546ff4287 100644 --- a/app/views/admin/contact_versions/show.haml +++ b/app/views/admin/contact_versions/show.haml @@ -1,6 +1,5 @@ -- attributes = only_present_fields(@version, Contact) -- contact = Contact.new(attributes) -- attach_existing_fields(@version, contact) +- contact = ObjectVersionsParser.new(@version).parse + = render 'shared/title', name: contact.name .row diff --git a/app/views/admin/contacts/index.haml b/app/views/admin/contacts/index.haml index 0812913a1..b5bfa89f1 100644 --- a/app/views/admin/contacts/index.haml +++ b/app/views/admin/contacts/index.haml @@ -11,11 +11,11 @@ .col-md-3 .form-group = f.label t(:id) - = f.search_field :code_matches, class: 'form-control', placeholder: t(:id) + = f.search_field :code_matches, value: params[:q][:code_matches], class: 'form-control', placeholder: t(:id) .col-md-3 .form-group = f.label t(:ident) - = f.search_field :ident_matches, class: 'form-control', placeholder: t(:ident) + = f.search_field :ident_matches, value: params[:q][:ident_matches], class: 'form-control', placeholder: t(:ident) .col-md-3 .form-group = label_tag t(:ident_type) @@ -24,7 +24,7 @@ .col-md-3 .form-group = f.label t(:email) - = f.search_field :email_matches, class: 'form-control', placeholder: t(:email) + = f.search_field :email_matches, value: params[:q][:email_matches], class: 'form-control', placeholder: t(:email) .col-md-3 .form-group = label_tag t(:country) @@ -63,10 +63,6 @@ .form-group = label_tag :only_no_country_code, "Ident CC missing" = check_box_tag :only_no_country_code, '1',params[:only_no_country_code].eql?('1'), style: 'width:auto;height:auto;float:right' - .col-md-3 - .form-group - = label_tag :email_verification_failed, "Email verification failed" - = check_box_tag :email_verification_failed, '1',params[:email_verification_failed].eql?('1'), style: 'width:auto;height:auto;float:right' .row .col-md-3{style: 'padding-top: 25px;float:right;padding-right: 0px'} diff --git a/app/views/admin/domain_versions/archive.haml b/app/views/admin/domain_versions/archive.haml index ec2034ed1..85105b9f0 100644 --- a/app/views/admin/domain_versions/archive.haml +++ b/app/views/admin/domain_versions/archive.haml @@ -62,9 +62,7 @@ %tbody - @versions.each do |version| - if version - - attributes = only_present_fields(version, Domain) - - domain = Domain.new(attributes) - - attach_existing_fields(version, domain) unless version.event == 'destroy' + - domain = ObjectVersionsParser.new(version).parse %tr %td= link_to(domain.name, admin_domain_version_path(version.id)) diff --git a/app/views/admin/domain_versions/show.haml b/app/views/admin/domain_versions/show.haml index 11f70599f..ab49dffee 100644 --- a/app/views/admin/domain_versions/show.haml +++ b/app/views/admin/domain_versions/show.haml @@ -1,6 +1,4 @@ -- present_fields = only_present_fields(@version, Domain) -- domain = Domain.new(present_fields) -- attach_existing_fields(@version, domain) unless @version.event == 'destroy' +- domain = ObjectVersionsParser.new(@version).parse - if @version - children = HashWithIndifferentAccess.new(@version.children) diff --git a/app/views/admin/domains/_search_form.html.erb b/app/views/admin/domains/_search_form.html.erb index ecfdd1ced..a59abeec5 100644 --- a/app/views/admin/domains/_search_form.html.erb +++ b/app/views/admin/domains/_search_form.html.erb @@ -9,19 +9,19 @@
<%= f.label :registrant_ident, for: nil %> - <%= f.search_field :registrant_ident_eq, class: 'form-control', placeholder: t(:registrant_ident) %> + <%= f.search_field :registrant_ident_matches, value: params[:q][:registrant_ident_matches], class: 'form-control', placeholder: t(:registrant_ident) %>
<%= f.label :contact_ident, for: nil %> - <%= f.search_field :contacts_ident_eq, class: 'form-control', placeholder: t(:contact_ident) %> + <%= f.search_field :contacts_ident_matches, value: params[:q][:contacts_ident_matches], class: 'form-control', placeholder: t(:contact_ident) %>
<%= f.label :nameserver_hostname, for: nil %> - <%= f.search_field :nameservers_hostname_eq, class: 'form-control', placeholder: t(:nameserver_hostname) %> + <%= f.search_field :nameservers_hostname_matches, value: params[:q][:nameservers_hostname_matches], class: 'form-control', placeholder: t(:nameserver_hostname) %>
diff --git a/app/views/admin/epp_logs/index.haml b/app/views/admin/epp_logs/index.haml index e657bd7fe..01e63dfcb 100644 --- a/app/views/admin/epp_logs/index.haml +++ b/app/views/admin/epp_logs/index.haml @@ -22,12 +22,12 @@ .col-md-3 .form-group = f.label :api_user - = f.search_field :api_user_name_cont, class: 'form-control', placeholder: t(:api_user), autocomplete: 'off' + = f.search_field :api_user_name_matches, value: params[:q][:api_user_name_matches], class: 'form-control', placeholder: t(:api_user), autocomplete: 'off' .row .col-md-3 .form-group = f.label :registrar - = f.select :api_user_registrar_cont, Registrar.all.map { |x| [x, x.name] }, { include_blank: true }, class: 'form-control', placeholder: t(:choose) + = f.select :api_user_registrar_matches, Registrar.all.map { |x| [x, x.name] }, { include_blank: true }, class: 'form-control', placeholder: t(:choose) .col-md-3 .form-group = f.label t(:created_after) diff --git a/app/views/admin/invoices/new.haml b/app/views/admin/invoices/new.haml index 920b11903..f688cfe04 100644 --- a/app/views/admin/invoices/new.haml +++ b/app/views/admin/invoices/new.haml @@ -12,7 +12,7 @@ .col-md-4.control-label = f.label :registrar_id, class: 'required' .col-md-8 - = f.select :registrar_id, Registrar.all.map { |r| [r.name, r.id] }, { include_blank: true }, class: 'form-control selectize', required: true + = select_tag 'deposit[registrar_id]', options_for_select(Registrar.all.map { |r| [r.name, r.id] }), { prompt: t(:choose), required: true, class: 'form-control js-combobox' } .form-group .col-md-4.control-label diff --git a/app/views/admin/repp_logs/index.haml b/app/views/admin/repp_logs/index.haml index b2aadcae3..e90881645 100644 --- a/app/views/admin/repp_logs/index.haml +++ b/app/views/admin/repp_logs/index.haml @@ -20,13 +20,12 @@ .col-md-3 .form-group = f.label :api_user - = f.search_field :api_user_name_cont, class: 'form-control', placeholder: t(:api_user), autocomplete: 'off' + = f.search_field :api_user_name_matches, value: params[:q][:api_user_name_matches], class: 'form-control', placeholder: t(:api_user), autocomplete: 'off' .row .col-md-3 .form-group = f.label :registrar - = f.select :api_user_registrar_cont, Registrar.all.map { |x| [x, x.name] }, { include_blank: true }, class: 'form-control', placeholder: t(:choose) - -# = f.search_field :api_user_registrar_cont, class: 'form-control', placeholder: t(:registrar_name), autocomplete: 'off' + = f.select :api_user_registrar_matches, Registrar.all.map { |x| [x, x.name] }, { include_blank: true }, class: 'form-control', placeholder: t(:choose) .col-md-3 .form-group = f.label t(:created_after) diff --git a/app/views/admin/reserved_domains/index.html.erb b/app/views/admin/reserved_domains/index.html.erb new file mode 100644 index 000000000..109dbad9a --- /dev/null +++ b/app/views/admin/reserved_domains/index.html.erb @@ -0,0 +1,137 @@ +<% content_for :actions do %> + <%= link_to(t('.new_btn'), new_admin_reserved_domain_path, class: 'btn btn-primary') %> +<% end %> + +<%= render 'shared/title', name: t('.title') %> +
+
+ <%= search_form_for [:admin, @q], html: { style: 'margin-bottom: 0;', class: 'js-form', autocomplete: 'off' } do |f| %> +
+
+
+ <%= f.label :name %> + <%= f.search_field :name_matches, value: params[:q][:name_matches], class: 'form-control', placeholder: t(:name) %> +
+
+
+
+ <%= f.label t(:created_at_from) %> + <%= f.search_field :created_at_gteq, value: params[:q][:created_at_gteq], class: 'form-control js-datepicker', placeholder: t(:created_at_from) %> +
+
+
+
+ <%= f.label t(:created_at_until) %> + <%= f.search_field :created_at_lteq, value: params[:q][:created_at_lteq], class: 'form-control js-datepicker', placeholder: t(:created_at_until) %> +
+
+
+
+
+
+ <%= label_tag t(:results_per_page) %> + <%= text_field_tag :results_per_page, params[:results_per_page], class: 'form-control', placeholder: t(:results_per_page) %> +
+
+
+ + <%= link_to(t('.csv_btn'), admin_reserved_domains_path(format: :csv, params: params.permit!), class: 'btn btn-default') %> + <%= link_to(t('.reset_btn'), admin_reserved_domains_path, class: 'btn btn-default') %> +
+
+ <% end %> +
+
+ +
+ +<%= form_for :reserved_elements, url: release_to_auction_admin_reserved_domains_path, html: { class: 'form-horizontal', autocomplete: 'off' } do |f| %> +
+ <%= f.submit 'Send to the auction list', class: 'btn btn-primary', style: 'margin: 10px 0 20px 0;' %> + Domains will be removed from reserved list! +
+ +
+
+
+ + + + + + + + + + + + + <% @domains.each do |x| %> + + + + + + + + + <% end %> + +
+ <%= check_box_tag :check_all %> + + <%= sort_link(@q, 'name') %> + + <%= sort_link(@q, 'password') %> + + <%= sort_link(@q, 'created_at', t(:created_at)) %> + + <%= sort_link(@q, 'updated_at', t(:updated_at)) %> + + <%= t(:actions) %> +
+ <%= f.check_box :domain_ids, { multiple: true }, x.id, nil %> + + <%= x.name %> + + <%= x.password %> + + <%= l(x.created_at, format: :short) %> + + <%= l(x.updated_at, format: :short) %> + + <%= link_to(t(:edit_pw), edit_admin_reserved_domain_path(id: x.id), class: 'btn btn-primary btn-xs') %> + <%= link_to(t(:delete), delete_admin_reserved_domain_path(id: x.id), data: { confirm: t(:are_you_sure) }, class: 'btn btn-danger btn-xs') %> +
+
+
+
+<% end %> + +
+
+ <%= paginate @domains %> +
+
+ +
+
+ + \ No newline at end of file diff --git a/app/views/admin/reserved_domains/index.haml b/app/views/admin/reserved_domains/index2.haml similarity index 90% rename from app/views/admin/reserved_domains/index.haml rename to app/views/admin/reserved_domains/index2.haml index 5444ba34d..a3b49e0b0 100644 --- a/app/views/admin/reserved_domains/index.haml +++ b/app/views/admin/reserved_domains/index2.haml @@ -30,6 +30,7 @@   = link_to(t('.csv_btn'), admin_reserved_domains_path(format: :csv, params: params.permit!), class: 'btn btn-default') = link_to(t('.reset_btn'), admin_reserved_domains_path, class: 'btn btn-default') + = link_to 'Send to auction',release_to_auction_admin_reserved_domains_path, method: :post, class: 'btn btn-default', style: 'margin-top: 5px;' %hr .row .col-md-12 @@ -37,6 +38,7 @@ %table.table.table-hover.table-bordered.table-condensed %thead %tr + %th{class: 'col-xs-1'} %th{class: 'col-xs-2'} = sort_link(@q, 'name') %th{class: 'col-xs-2'} @@ -50,6 +52,8 @@ %tbody - @domains.each do |x| %tr + %td{class: 'text-center'} + = check_box_tag "reserved_domains[domain_ids][]", x.id, false %td= x.name %td= x.password %td= l(x.created_at, format: :short) diff --git a/app/views/epp/contacts/check.xml.builder b/app/views/epp/contacts/check.xml.builder index 6b4ea4cc7..f3b1f555a 100644 --- a/app/views/epp/contacts/check.xml.builder +++ b/app/views/epp/contacts/check.xml.builder @@ -5,15 +5,7 @@ xml.epp_head do end xml.resData do - xml.tag!('contact:chkData', 'xmlns:contact' => - Xsd::Schema.filename(for_prefix: 'contact-ee', for_version: '1.1')) do - @results.each do |result| - xml.tag!('contact:cd') do - xml.tag! "contact:id", result[:code], avail: result[:avail] - xml.tag!('contact:reason', result[:reason]) unless result[:avail] == 1 - end - end - end + xml << render('epp/contacts/partials/check', builder: xml, results: @results) end render('epp/shared/trID', builder: xml) diff --git a/app/views/epp/contacts/partials/_check.xml.builder b/app/views/epp/contacts/partials/_check.xml.builder new file mode 100644 index 000000000..70bb1f4e3 --- /dev/null +++ b/app/views/epp/contacts/partials/_check.xml.builder @@ -0,0 +1,9 @@ +builder.tag!('contact:chkData', 'xmlns:contact' => + Xsd::Schema.filename(for_prefix: 'contact-ee', for_version: '1.1')) do + results.each do |result| + builder.tag!('contact:cd') do + builder.tag! 'contact:id', result[:code], avail: result[:avail] + # builder.tag!('contact:reason', result[:reason]) unless result[:avail] == 1 + end + end +end diff --git a/app/views/epp/domains/info.xml.builder b/app/views/epp/domains/info.xml.builder index b154752e9..cc2190dc4 100644 --- a/app/views/epp/domains/info.xml.builder +++ b/app/views/epp/domains/info.xml.builder @@ -11,7 +11,7 @@ xml.epp_head do xml.tag!('domain:name', @domain.name) xml.tag!('domain:roid', @domain.roid) @domain.statuses.each do |s| - xml.tag!('domain:status', 's' => s) + xml.tag!('domain:status', @domain.status_notes[s], 's' => s) end xml.tag!('domain:registrant', @domain.registrant.code) diff --git a/app/views/epp/poll/_action.xml.builder b/app/views/epp/poll/_action.xml.builder deleted file mode 100644 index dc0adb4e4..000000000 --- a/app/views/epp/poll/_action.xml.builder +++ /dev/null @@ -1,9 +0,0 @@ -builder.extension do - builder.tag!('changePoll:changeData', - 'xmlns:changePoll' => Xsd::Schema.filename(for_prefix: 'changePoll')) do - builder.tag!('changePoll:operation', action.operation) - builder.tag!('changePoll:date', action.created_at.utc.xmlschema) - builder.tag!('changePoll:svTRID', action.id) - builder.tag!('changePoll:who', action.user) - end -end diff --git a/app/views/epp/poll/_extension.xml.builder b/app/views/epp/poll/_extension.xml.builder new file mode 100644 index 000000000..5a17995df --- /dev/null +++ b/app/views/epp/poll/_extension.xml.builder @@ -0,0 +1,21 @@ +builder.extension do + builder.tag!('changePoll:changeData', + 'xmlns:changePoll' => Xsd::Schema.filename(for_prefix: 'changePoll', + for_version: '1.0')) do + case type + when 'action' + builder.tag!('changePoll:operation', obj.operation) + builder.tag!('changePoll:date', obj.created_at.utc.xmlschema) + builder.tag!('changePoll:svTRID', obj.id) + builder.tag!('changePoll:who', obj.user) + if obj.bulk_action? + builder.tag!( + 'changePoll:reason', + 'Auto-update according to official data' + ) + end + when 'state' + builder.tag!('changePoll:operation', obj) + end + end +end diff --git a/app/views/epp/poll/poll_req.xml.builder b/app/views/epp/poll/poll_req.xml.builder index a1f12fd65..0a916e6ad 100644 --- a/app/views/epp/poll/poll_req.xml.builder +++ b/app/views/epp/poll/poll_req.xml.builder @@ -9,27 +9,35 @@ xml.epp_head do xml.msg @notification.text end - if @notification.attached_obj_type == 'DomainTransfer' && @object - xml.resData do - xml << render('epp/domains/partials/transfer', builder: xml, dt: @object) + if @object + case @notification.attached_obj_type + when 'DomainTransfer' + xml.resData do + xml << render('epp/domains/partials/transfer', builder: xml, dt: @object) + end + when 'BulkAction' + xml.resData do + xml << render( + 'epp/contacts/partials/check', + builder: xml, + results: @object.to_non_available_contact_codes + ) + end end end - if @notification.action&.contact || @notification.registry_lock? + if @notification.action || @notification.registry_lock? if @notification.registry_lock? state = @notification.text.include?('unlocked') ? 'unlock' : 'lock' - xml.extension do - xml.tag!('changePoll:changeData', - 'xmlns:changePoll': Xsd::Schema.filename(for_prefix: 'changePoll')) do - xml.tag!('changePoll:operation', state) - end - end + render(partial: 'epp/poll/extension', + locals: { builder: xml, + obj: state, + type: 'state' }) else - render(partial: 'epp/poll/action', - locals: { - builder: xml, - action: @notification.action, - }) + render(partial: 'epp/poll/extension', + locals: { builder: xml, + obj: @notification.action, + type: 'action' }) end end diff --git a/app/views/layouts/registrant/application.html.erb b/app/views/layouts/registrant/application.html.erb deleted file mode 100644 index c5290b70f..000000000 --- a/app/views/layouts/registrant/application.html.erb +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - <% if content_for? :head_title %> - <%= yield :head_title %> - <% else %> - - <%= t(:registrant_head_title) %> - - <% end %> - <%= csrf_meta_tags %> - <%= stylesheet_link_tag 'registrant-manifest', media: 'all' %> - <%= favicon_link_tag 'favicon.ico' %> - - - - -
- <%= render 'flash_messages' %> - <%= yield %> -
- - <%= javascript_include_tag 'registrant-manifest', async: true %> - - diff --git a/app/views/mailers/domain_delete_mailer/forced/invalid_email.html.erb b/app/views/mailers/domain_delete_mailer/forced/invalid_email.html.erb deleted file mode 100644 index 817538afd..000000000 --- a/app/views/mailers/domain_delete_mailer/forced/invalid_email.html.erb +++ /dev/null @@ -1,47 +0,0 @@ -

Lugupeetud domeeni <%= @domain.name %> registreerija/halduskontakt

- -

Eesti Interneti Sihtasutusele (EIS) on saanud teatavaks, et domeeni <%= @domain.name %> kontaktandmed on puudulikud - eposti aadress <%= @domain.contact_emails_verification_failed %>.

- -

Et see olukord on vastuolus .ee domeenireeglitega algatas EIS <%= @delete_period_length %> päeva pikkuse kustutusmenetluse. Menetluse käigus on domeen <%= @expire_warning_period %> esimest päeva internetis kättesaadav.

- -

Andmete parandamiseks pöörduge palun oma registripidaja <%= @registrar.name %> poole või isiklike ja oma ettevõtte andmete puhul registreerija portaali.

- -

Kui kontaktandmed ei ole <%= @delete_period_length %> päeva jooksul parandatud, läheb domeen <%= @domain.name %> <%= @domain.force_delete_date %> domeenioksjonile .ee oksjonikeskkonda. Juhul kui domeenile <%= @domain.name %> ei tehta oksjonil 24h möödudes pakkumist, domeen vabaneb ja on registreerimiseks vabalt kättesaadav kõigile huvilistele. Muude võimalike oksjoni tulemuste kohta loe siit.

- -

Lisaküsimuste korral võtke palun ühendust oma registripidajaga:

-<%= render 'mailers/shared/registrar/registrar.et.html', registrar: @registrar %> - -<%= render 'mailers/shared/signatures/signature.et.html' %> - -
- -

Dear registrant/administrative contact of .ee domain,

- -

Estonian Internet Foundation has learned that contact data of the domain <%= @domain.name %> s invalid - email(s) <%= @domain.contact_emails_verification_failed %>.

- -

Since this is a violation of Estonian domain regulations, <%= @delete_period_length %>-day deletion process has started for the <%= @domain.name %> domain. For the first <%= @expire_warning_period %> days the domain will remain available on the Internet during the deletion process.

- -

Please, contact your registrar <%= @registrar.name %> with updated contact data, or in case of your personal or business data use .ee portal for registrants

- -

If the data is not fixed within <%= @delete_period_length %> days, the domain <%= @domain.name %> will go to domain auction on <%= @domain.force_delete_date %> in the .ee auction environment. If no offer is made for the domain <%= @domain.name %> at auction within 24 hours, the domain will be released and made freely available for registration to anyone interested on a first-come, first-served basis. Read more about other potential auction results here.

- -

Should you have additional questions, please contact your registrar:

-<%= render 'mailers/shared/registrar/registrar.en.html', registrar: @registrar %> - -<%= render 'mailers/shared/signatures/signature.en.html' %> -
- -

Уважаемый регистрант/административный контакт домена .ee

- -

Целевому учреждению Eesti Internet (EIS) стало известно, что контактные данные домена <%= @registrant.reg_no %> неверны - электронная почта <%= @domain.contact_emails_verification_failed %>.

- -

Так как это является нарушением Правил домена .ee, <%= @delete_period_length %>-дневный процесс удаления начат для доменного имени <%= @domain.name %>. В течение первых <%= @expire_warning_period %> дней домен будет доступен в интернете.

- -

Для уточнения контактных данных, пожалуйста, свяжитесь с регистратором <%= @registrar.name %>, либо воспользуйтесь порталом для регистрантов

- -

Если контактные данные не будут исправлены в течение <%= @delete_period_length %> дней, домен <%= @domain.name %> отправится <%= @domain.force_delete_date %> на доменный аукцион в аукционной среде.ee. Если в течение 24 часов в отношении домена <%= @domain.name %> е поступит предложений, домен освободится и станет доступным для всех желающих по принципу «кто раньше». О других возможных результатах аукциона читайте здесь.

- -

В случае возникновения дополнительных вопросов свяжитесь, пожалуйста, со своим регистратором: -<%= render 'mailers/shared/registrar/registrar.ru.html', registrar: @registrar %>

- -<%= render 'mailers/shared/signatures/signature.ru.html' %> diff --git a/app/views/mailers/domain_delete_mailer/forced/invalid_email.text.erb b/app/views/mailers/domain_delete_mailer/forced/invalid_email.text.erb deleted file mode 100644 index 8d2fc58ce..000000000 --- a/app/views/mailers/domain_delete_mailer/forced/invalid_email.text.erb +++ /dev/null @@ -1,47 +0,0 @@ -

Lugupeetud domeeni <%= @domain.name %> registreerija/halduskontakt

- -

Eesti Interneti Sihtasutusele (EIS) on saanud teatavaks, et domeeni <%= @domain.name %> kontaktandmed on puudulikud - eposti aadress <%= @domain.contact_emails_verification_failed %>

- -

Et see olukord on vastuolus .ee domeenireeglitega algatas EIS <%= @delete_period_length %> päeva pikkuse kustutusmenetluse. Menetluse käigus on domeen <%= @expire_warning_period %> esimest päeva internetis kättesaadav.

- -

Andmete parandamiseks pöörduge palun oma registripidaja <%= @registrar.name %> poole või isiklike ja oma ettevõtte andmete puhul registreerija portaali.

- -

Kui kontaktandmed ei ole <%= @delete_period_length %> päeva jooksul parandatud, läheb domeen <%= @domain.name %> <%= @domain.force_delete_date %> domeenioksjonile .ee oksjonikeskkonda. Juhul kui domeenile <%= @domain.name %> ei tehta oksjonil 24h möödudes pakkumist, domeen vabaneb ja on registreerimiseks vabalt kättesaadav kõigile huvilistele. Muude võimalike oksjoni tulemuste kohta loe siit.

- -

Lisaküsimuste korral võtke palun ühendust oma registripidajaga:

-<%= render 'mailers/shared/registrar/registrar.et.html', registrar: @registrar %> - -<%= render 'mailers/shared/signatures/signature.et.html' %> - -
- -

Dear registrant/administrative contact of .ee domain,

- -

Estonian Internet Foundation has learned that contact data of the domain <%= @domain.name %> s invalid - email(s) <%= @domain.contact_emails_verification_failed %>.

- -

Since this is a violation of Estonian domain regulations, <%= @delete_period_length %>-day deletion process has started for the <%= @domain.name %> domain. For the first <%= @expire_warning_period %> days the domain will remain available on the Internet during the deletion process.

- -

Please, contact your registrar <%= @registrar.name %> with updated contact data, or in case of your personal or business data use .ee portal for registrants

- -

If the data is not fixed within <%= @delete_period_length %> days, the domain <%= @domain.name %> will go to domain auction on <%= @domain.force_delete_date %> in the .ee auction environment. If no offer is made for the domain <%= @domain.name %> at auction within 24 hours, the domain will be released and made freely available for registration to anyone interested on a first-come, first-served basis. Read more about other potential auction results here.

- -

Should you have additional questions, please contact your registrar:

-<%= render 'mailers/shared/registrar/registrar.en.html', registrar: @registrar %> - -<%= render 'mailers/shared/signatures/signature.en.html' %> -
- -

Уважаемый регистрант/административный контакт домена .ee

- -

Целевому учреждению Eesti Internet (EIS) стало известно, что контактные данные домена <%= @registrant.reg_no %> неверны - электронная почта <%= @domain.contact_emails_verification_failed %>.

- -

Так как это является нарушением Правил домена .ee, <%= @delete_period_length %>-дневный процесс удаления начат для доменного имени <%= @domain.name %>. В течение первых <%= @expire_warning_period %> дней домен будет доступен в интернете.

- -

Для уточнения контактных данных, пожалуйста, свяжитесь с регистратором <%= @registrar.name %>, либо воспользуйтесь порталом для регистрантов

- -

Если контактные данные не будут исправлены в течение <%= @delete_period_length %> дней, домен <%= @domain.name %> отправится <%= @domain.force_delete_date %> на доменный аукцион в аукционной среде.ee. Если в течение 24 часов в отношении домена <%= @domain.name %> е поступит предложений, домен освободится и станет доступным для всех желающих по принципу «кто раньше». О других возможных результатах аукциона читайте здесь.

- -

В случае возникновения дополнительных вопросов свяжитесь, пожалуйста, со своим регистратором: - <%= render 'mailers/shared/registrar/registrar.ru.html', registrar: @registrar %>

- -<%= render 'mailers/shared/signatures/signature.ru.html' %> diff --git a/app/views/registrar/domains/partials/_statuses.haml b/app/views/registrar/domains/partials/_statuses.haml index 57ecc4105..125309caf 100644 --- a/app/views/registrar/domains/partials/_statuses.haml +++ b/app/views/registrar/domains/partials/_statuses.haml @@ -6,7 +6,7 @@ %thead %tr %th{class: 'col-xs-6'}= t(:status) - %th{class: 'col-xs-6'}= t(:description) + %th{class: 'col-xs-6'}= t(:notes) %tbody - @data.css('status').each do |x| %tr diff --git a/config/locales/en.yml b/config/locales/en.yml index 2f7e8a0aa..9c396cbde 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -96,8 +96,6 @@ en: contact: blank: 'Contact was not found' taken: 'Contact already exists on this domain' - contact_code_cache: - taken: 'Contact already exists on this domain' domain_status: attributes: @@ -189,6 +187,7 @@ en: log_out: 'Log out (%{user})' system: 'System' domains: 'Domains' + auctions: 'Auctions' registrars: 'Registrars' valid_to: 'Valid to' name: 'Name' @@ -371,7 +370,7 @@ en: sim_error: 'SIM application error' internal_error: 'Internal error' client_side_status_editing_error: 'Parameter value policy error. Client-side object status management not supported' - parameter_value_syntax_error: 'Parameter value syntax error: ' + parameter_value_syntax_error: 'Parameter value syntax error:' # DEPP activemodel: @@ -627,7 +626,7 @@ en: contact_ident: 'Contact ident' results_per_page: 'Results per page' nameserver_hostname: 'Nameserver hostname' - result_count: + result_count: zero: 'No results' other: '%{count} results' one: '1 result' diff --git a/config/locales/notifications.en.yml b/config/locales/notifications.en.yml index b5c1dfd47..3bd65ea7e 100644 --- a/config/locales/notifications.en.yml +++ b/config/locales/notifications.en.yml @@ -6,6 +6,7 @@ en: It was associated with registrant %{old_registrant_code} and contacts %{old_contacts_codes}. contact_update: Contact %{contact} has been updated by registrant + contact_bulk_update: '%{count} contacts have been updated by registrant' csync: CSYNC DNSSEC %{action} for domain %{domain} registrar_locked: Domain %{domain_name} has been locked by registrant registrar_unlocked: Domain %{domain_name} has been unlocked by registrant diff --git a/config/locales/registrar/domains.en.yml b/config/locales/registrar/domains.en.yml index b8605bd42..be2574d92 100644 --- a/config/locales/registrar/domains.en.yml +++ b/config/locales/registrar/domains.en.yml @@ -1,6 +1,8 @@ en: registrar: domains: + email_error_message: 'Check contacts emails' + index: header: Domains new_btn: New domain diff --git a/config/routes.rb b/config/routes.rb index 66debd4b4..4ba44300d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -128,7 +128,11 @@ Rails.application.routes.draw do resources :domains, only: %i[index show], param: :uuid do resource :registry_lock, only: %i[create destroy] end - resources :contacts, only: %i[index show update], param: :uuid + resources :contacts, only: %i[index show update], param: :uuid do + get 'do_need_update_contacts', to: 'contacts#do_need_update_contacts', + as: :do_need_update_contacts + post 'update_contacts', to: 'contacts#update_contacts', as: :update_contacts + end resources :companies, only: %i[index] end @@ -262,6 +266,13 @@ Rails.application.routes.draw do resources :accounts resources :account_activities + resources :auctions, only: [ :index, :create ] do + collection do + post 'upload_spreadsheet', to: 'auctions#upload_spreadsheet', as: :upload_spreadsheet + end + end + # post 'admi/upload_spreadsheet', to: 'customers#upload_spreadsheet', as: :customers_upload_spreadsheet + resources :bank_statements do resources :bank_transactions @@ -331,6 +342,10 @@ Rails.application.routes.draw do member do get 'delete' end + + collection do + post 'release_to_auction', to: 'reserved_domains#release_to_auction', as: 'release_to_auction' + end end resources :disputes do member do diff --git a/db/migrate/20141210085432_add_code_cache_for_domain_contact.rb b/db/migrate/20141210085432_add_code_cache_for_domain_contact.rb index c3c71ff35..d3aac8296 100644 --- a/db/migrate/20141210085432_add_code_cache_for_domain_contact.rb +++ b/db/migrate/20141210085432_add_code_cache_for_domain_contact.rb @@ -1,10 +1,10 @@ class AddCodeCacheForDomainContact < ActiveRecord::Migration[6.0] def change - add_column :domain_contacts, :contact_code_cache, :string - - DomainContact.all.each do |x| - x.contact_code_cache = x.contact.code - x.save - end + # add_column :domain_contacts, :contact_code_cache, :string + # + # DomainContact.all.each do |x| + # x.contact_code_cache = x.contact.code + # x.save + # end end end diff --git a/db/migrate/20220113201642_add_email_history_to_contacts.rb b/db/migrate/20220113201642_add_email_history_to_contacts.rb new file mode 100644 index 000000000..2a5f59953 --- /dev/null +++ b/db/migrate/20220113201642_add_email_history_to_contacts.rb @@ -0,0 +1,9 @@ +class AddEmailHistoryToContacts < ActiveRecord::Migration[6.1] + def change + add_column :contacts, :email_history, :string + + reversible do |dir| + dir.up { Contact.update_all('email_history = email') } + end + end +end diff --git a/db/migrate/20220113220809_add_email_history_to_registrars.rb b/db/migrate/20220113220809_add_email_history_to_registrars.rb new file mode 100644 index 000000000..1f89353a1 --- /dev/null +++ b/db/migrate/20220113220809_add_email_history_to_registrars.rb @@ -0,0 +1,9 @@ +class AddEmailHistoryToRegistrars < ActiveRecord::Migration[6.1] + def change + add_column :registrars, :email_history, :string + + reversible do |dir| + dir.up { Registrar.update_all('email_history = email') } + end + end +end diff --git a/db/migrate/20220228093211_add_failed_validation_reasong_to_dnskey.rb b/db/migrate/20220228093211_add_failed_validation_reasong_to_dnskey.rb new file mode 100644 index 000000000..6d61f385f --- /dev/null +++ b/db/migrate/20220228093211_add_failed_validation_reasong_to_dnskey.rb @@ -0,0 +1,5 @@ +class AddFailedValidationReasongToDnskey < ActiveRecord::Migration[6.1] + def change + add_column :dnskeys, :failed_validation_reason, :string + end +end diff --git a/db/migrate/20220316140727_add_bulk_actions.rb b/db/migrate/20220316140727_add_bulk_actions.rb new file mode 100644 index 000000000..1eae94220 --- /dev/null +++ b/db/migrate/20220316140727_add_bulk_actions.rb @@ -0,0 +1,5 @@ +class AddBulkActions < ActiveRecord::Migration[6.1] + def change + add_column :actions, :bulk_action_id, :integer, default: nil + end +end diff --git a/db/migrate/20220412130856_add_type_to_auction.rb b/db/migrate/20220412130856_add_type_to_auction.rb new file mode 100644 index 000000000..14714e868 --- /dev/null +++ b/db/migrate/20220412130856_add_type_to_auction.rb @@ -0,0 +1,5 @@ +class AddTypeToAuction < ActiveRecord::Migration[6.1] + def change + add_column :auctions, :platform, :integer, null: true + end +end diff --git a/db/migrate/20220413073315_remove_email_address_verifications.rb b/db/migrate/20220413073315_remove_email_address_verifications.rb new file mode 100644 index 000000000..db1f4230c --- /dev/null +++ b/db/migrate/20220413073315_remove_email_address_verifications.rb @@ -0,0 +1,5 @@ +class RemoveEmailAddressVerifications < ActiveRecord::Migration[6.1] + def change + # drop_table :email_address_verifications + end +end diff --git a/db/migrate/20220413084536_remove_email_addresses_validations.rb b/db/migrate/20220413084536_remove_email_addresses_validations.rb new file mode 100644 index 000000000..0084dc08e --- /dev/null +++ b/db/migrate/20220413084536_remove_email_addresses_validations.rb @@ -0,0 +1,5 @@ +class RemoveEmailAddressesValidations < ActiveRecord::Migration[6.1] + def change + # drop_table :email_addresses_validations + end +end diff --git a/db/migrate/20220413084748_remove_email_addresses_verifications.rb b/db/migrate/20220413084748_remove_email_addresses_verifications.rb new file mode 100644 index 000000000..124086d86 --- /dev/null +++ b/db/migrate/20220413084748_remove_email_addresses_verifications.rb @@ -0,0 +1,5 @@ +class RemoveEmailAddressesVerifications < ActiveRecord::Migration[6.1] + def change + # drop_table :email_addresses_verifications + end +end diff --git a/db/migrate/20220504090512_remove_contact_code_cache_from_domain_contacts.rb b/db/migrate/20220504090512_remove_contact_code_cache_from_domain_contacts.rb new file mode 100644 index 000000000..a95d8e193 --- /dev/null +++ b/db/migrate/20220504090512_remove_contact_code_cache_from_domain_contacts.rb @@ -0,0 +1,5 @@ +class RemoveContactCodeCacheFromDomainContacts < ActiveRecord::Migration[6.1] + def change + remove_column :domain_contacts, :contact_code_cache + end +end diff --git a/db/structure.sql b/db/structure.sql index 4403facfb..66152fe27 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -304,7 +304,8 @@ CREATE TABLE public.actions ( user_id integer, operation character varying NOT NULL, created_at timestamp without time zone, - contact_id integer + contact_id integer, + bulk_action_id integer ); @@ -350,7 +351,8 @@ CREATE TABLE public.auctions ( uuid uuid DEFAULT public.gen_random_uuid() NOT NULL, created_at timestamp without time zone NOT NULL, registration_code character varying, - registration_deadline timestamp without time zone + registration_deadline timestamp without time zone, + platform integer ); @@ -667,7 +669,8 @@ CREATE TABLE public.contacts ( upid integer, up_date timestamp without time zone, uuid uuid DEFAULT public.gen_random_uuid() NOT NULL, - disclosed_attributes character varying[] DEFAULT '{}'::character varying[] NOT NULL + disclosed_attributes character varying[] DEFAULT '{}'::character varying[] NOT NULL, + email_history character varying ); @@ -825,7 +828,8 @@ CREATE TABLE public.dnskeys ( updator_str character varying, legacy_domain_id integer, updated_at timestamp without time zone, - validation_datetime timestamp without time zone + validation_datetime timestamp without time zone, + failed_validation_reason character varying ); @@ -858,7 +862,6 @@ CREATE TABLE public.domain_contacts ( domain_id integer, created_at timestamp without time zone, updated_at timestamp without time zone, - contact_code_cache character varying, creator_str character varying, updator_str character varying, type character varying, @@ -1193,6 +1196,7 @@ CREATE TABLE public.invoices ( buyer_vat_no character varying, issue_date date NOT NULL, e_invoice_sent_at timestamp without time zone, + payment_link character varying, CONSTRAINT invoices_due_date_is_not_before_issue_date CHECK ((due_date >= issue_date)) ); @@ -2501,7 +2505,8 @@ CREATE TABLE public.registrars ( iban character varying, settings jsonb DEFAULT '{}'::jsonb NOT NULL, legaldoc_optout boolean DEFAULT false NOT NULL, - legaldoc_optout_comment text + legaldoc_optout_comment text, + email_history character varying ); @@ -5395,7 +5400,17 @@ INSERT INTO "schema_migrations" (version) VALUES ('20211125184334'), ('20211126085139'), ('20211231113934'), -('20220106123143'); - +('20220106123143'), +('20220113201642'), +('20220113220809'), +('20220124105717'), +('20220216113112'), +('20220228093211'), +('20220316140727'), +('20220412130856'), +('20220413073315'), +('20220413084536'), +('20220413084748'), +('20220504090512'); diff --git a/doc/epp_examples.md b/doc/epp_examples.md index 7e0e001ba..62e0f818d 100644 --- a/doc/epp_examples.md +++ b/doc/epp_examples.md @@ -9979,12 +9979,6 @@ RESPONSE: ns2.example.com - - Contact already exists on this domain [contact_code_cache] - - FIXED:MAK21 - - Public key already exists [public_key] @@ -10504,12 +10498,6 @@ RESPONSE: ns.kozey114.ee - - Contact already exists on this domain [contact_code_cache] - - FIXED:SH6021836789 - - ABC-12345 ccReg-4475356063 @@ -14058,4 +14046,3 @@ RESPONSE: ``` - diff --git a/lib/serializers/repp/domain.rb b/lib/serializers/repp/domain.rb index 60863373c..d365859c1 100644 --- a/lib/serializers/repp/domain.rb +++ b/lib/serializers/repp/domain.rb @@ -15,7 +15,7 @@ module Serializers updated_at: obj.updated_at, expire_time: obj.expire_time, outzone_at: obj.outzone_at, delete_date: obj.delete_date, force_delete_date: obj.force_delete_date, contacts: contacts, nameservers: nameservers, dnssec_keys: dnssec_keys, - statuses: obj.statuses, registrar: registrar + statuses: obj.status_notes, registrar: registrar } json[:transfer_code] = obj.auth_info if @sponsored json @@ -23,7 +23,7 @@ module Serializers # rubocop:enable Metrics/AbcSize def contacts - domain.domain_contacts.map { |c| { code: c.contact_code_cache, type: c.type } } + domain.domain_contacts.map { |c| { code: c.contact.code, type: c.type } } end def nameservers diff --git a/lib/tasks/check_closed_disputes.rake b/lib/tasks/check_closed_disputes.rake new file mode 100644 index 000000000..52f863c69 --- /dev/null +++ b/lib/tasks/check_closed_disputes.rake @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +namespace :disputes do + desc 'Check closed disputes with expired_at in the Past' + task check_closed: :environment do + DisputeStatusUpdateJob.perform_now(include_closed: true) + end +end diff --git a/lib/tasks/check_force_delete.rake b/lib/tasks/check_force_delete.rake new file mode 100644 index 000000000..7bb66b743 --- /dev/null +++ b/lib/tasks/check_force_delete.rake @@ -0,0 +1,12 @@ +desc 'Check Force Delete' +task check_force_delete: :environment do + validations = ValidationEvent.select(:validation_eventable_id) + .failed.where(validation_eventable_type: 'Contact') + .group(:validation_eventable_id) + + invalid_contact_ids = ( + validations.mx.having("count(event_data ->> 'success') > 2") + validations.regex + ).pluck(:validation_eventable_id) + + CheckForceDeleteJob.perform_later(invalid_contact_ids) +end diff --git a/lib/tasks/migrate_domain_statuses.rake b/lib/tasks/migrate_domain_statuses.rake deleted file mode 100644 index 8c68f9e70..000000000 --- a/lib/tasks/migrate_domain_statuses.rake +++ /dev/null @@ -1,10 +0,0 @@ -namespace :migrate_domain_statuses do - desc 'Starts collect invalid validation contacts' - task fd_domains: :environment do - MigrateBeforeForceDeleteStatusesJob.perform_later - end - - task admin_status_history: :environment do - MigrateStatusesToDomainHistoryJob.perform_later - end -end diff --git a/lib/tasks/verify_email.rake b/lib/tasks/verify_email.rake index c22587ab1..b90fde0d6 100644 --- a/lib/tasks/verify_email.rake +++ b/lib/tasks/verify_email.rake @@ -18,17 +18,12 @@ namespace :verify_email do options = RakeOptionParserBoilerplate.process_args(options: options, banner: banner, hash: opts_hash) - - batch_contacts = prepare_contacts(options) - logger.info 'No contacts to check email selected' and next if batch_contacts.blank? - - batch_contacts.find_in_batches(batch_size: 10_000) do |contacts| - contacts.each do |contact| - VerifyEmailsJob.set(wait_until: spam_protect_timeout(options)).perform_later( - contact: contact, - check_level: check_level(options) - ) if filter_check_level(contact) - end + email_contacts = prepare_contacts(options) + email_contacts.each do |email| + VerifyEmailsJob.set(wait_until: spam_protect_timeout(options)).perform_later( + email: email, + check_level: check_level(options) + ) end end end @@ -56,55 +51,27 @@ def prepare_contacts(options) time = Time.zone.now - ValidationEvent::VALIDATION_PERIOD validation_events_ids = ValidationEvent.where('created_at > ?', time).distinct.pluck(:validation_eventable_id) - contacts_ids = Contact.where.not(id: validation_events_ids).pluck(:id) - Contact.where(id: contacts_ids + failed_contacts) + contacts_emails = Contact.where.not(id: validation_events_ids).pluck(:email) + (contacts_emails + failed_email_contacts).uniq end end -def filter_check_level(contact) - return true unless contact.validation_events.exists? - - data = contact.validation_events.order(created_at: :asc).last - - return true if data.successful? && data.created_at < (Time.zone.now - ValidationEvent::VALIDATION_PERIOD) - - if data.failed? - return false if data.event_data['check_level'] == 'regex' - - # return false if data.event_data['check_level'] == 'smtp' - # - # return false if check_mx_contact_validation(contact) - - return true - end - - false -end - -def failed_contacts +def failed_email_contacts failed_contacts = [] failed_validations_ids = ValidationEvent.failed.distinct.pluck(:validation_eventable_id) contacts = Contact.where(id: failed_validations_ids).includes(:validation_events) contacts.find_each(batch_size: 10_000) do |contact| - failed_contacts << contact.id if filter_check_level(contact) + failed_contacts << contact.email end failed_contacts.uniq end -# def check_mx_contact_validation(contact) -# data = contact.validation_events.mx.order(created_at: :asc).last(ValidationEvent::MX_CHECK) -# -# return false if data.size < ValidationEvent::MX_CHECK -# -# data.all? { |d| d.failed? } -# end - def contacts_by_domain(domain_name) domain = ::Domain.find_by(name: domain_name) return unless domain - domain.contacts + domain.contacts.pluck(:email).uniq end def opts_hash diff --git a/renovate.json b/renovate.json index a1a4fde6b..11d9ae957 100644 --- a/renovate.json +++ b/renovate.json @@ -9,17 +9,20 @@ "automergeType": "pr" }, { - "depTypeList": ["ruby", "bundler", "Gemfile", "Gemfile.lock"], + "matchDepTypes": ["ruby", "bundler", "Gemfile", "Gemfile.lock"], "addLabels": ["bundler"] }, { - "depTypeList": [".ruby-version"], + "matchDepTypes": [".ruby-version"], "addLabels": ["ruby-version"] } ], "docker": { "enabled": false }, + "ruby": { + "stabilityDays": 60 + }, "ignorePaths": [ "Dockerfile", "Dockerfile.*", ".github/workflows/build_deploy_staging.yml", ".github/workflows/remove_st_after_pr.yml" diff --git a/test/fixtures/actions.yml b/test/fixtures/actions.yml index 46736e0a1..b802679ba 100644 --- a/test/fixtures/actions.yml +++ b/test/fixtures/actions.yml @@ -2,4 +2,24 @@ contact_update: operation: update contact: john created_at: <%= Time.zone.parse('2010-07-05').to_s(:db) %> - user: registrant \ No newline at end of file + user: registrant + +contacts_update_bulk_action: + operation: bulk_update + user: registrant + +contact_update_subaction_one: + operation: update + contact: william + created_at: <%= Time.zone.parse('2010-07-05').to_s(:db) %> + user: registrant + bulk_action: contacts_update_bulk_action + +contact_update_subaction_two: + operation: update + contact: jane + created_at: <%= Time.zone.parse('2010-07-05').to_s(:db) %> + user: registrant + bulk_action: contacts_update_bulk_action + + diff --git a/test/fixtures/contacts.yml b/test/fixtures/contacts.yml index 4d45738bd..6e362d7a6 100644 --- a/test/fixtures/contacts.yml +++ b/test/fixtures/contacts.yml @@ -1,6 +1,7 @@ john: name: John email: john@inbox.test + email_history: john@inbox.test phone: '+555.555' ident: 1234 ident_type: priv @@ -18,6 +19,7 @@ john: william: &william name: William email: william@inbox.test + email_history: william@inbox.test phone: '+555.555' fax: '+666.6' ident: 12345 diff --git a/test/fixtures/files/accounts.csv b/test/fixtures/files/accounts.csv new file mode 100644 index 000000000..5bc44fc48 --- /dev/null +++ b/test/fixtures/files/accounts.csv @@ -0,0 +1,4 @@ +Id,Balance,Currency,Registrar +112846265,100.0,EUR,Best Names +298486374,100.0,EUR,Good Names +597560588,0.0,EUR,Not in use diff --git a/test/fixtures/files/auction_domains_list.csv b/test/fixtures/files/auction_domains_list.csv new file mode 100644 index 000000000..b216ceb8f --- /dev/null +++ b/test/fixtures/files/auction_domains_list.csv @@ -0,0 +1,3 @@ +name +tere.test +chao.test diff --git a/test/fixtures/files/auction_domains_list_with_invalid_item.csv b/test/fixtures/files/auction_domains_list_with_invalid_item.csv new file mode 100644 index 000000000..4ed7a83f1 --- /dev/null +++ b/test/fixtures/files/auction_domains_list_with_invalid_item.csv @@ -0,0 +1,4 @@ +name +tere.test +chao.test +cha.chacha diff --git a/test/fixtures/files/contact_versions.csv b/test/fixtures/files/contact_versions.csv new file mode 100644 index 000000000..c794026c2 --- /dev/null +++ b/test/fixtures/files/contact_versions.csv @@ -0,0 +1,3 @@ +Name,ID,Ident,Registrar,Action,Created at +,test_code,[ ],Best Names,update,2018-04-23 15:50:48 +,,[ ],,update,2010-07-04 21:00:00 diff --git a/test/fixtures/files/contacts.csv b/test/fixtures/files/contacts.csv new file mode 100644 index 000000000..9d8ca5357 --- /dev/null +++ b/test/fixtures/files/contacts.csv @@ -0,0 +1,2 @@ +Name,ID,Ident,E-mail,Created at,Registrar,Phone +Acme Ltd,acme-ltd-001,1234567 [US org],acme@outlook.test,2010-07-05 07:30:00,Best Names,+555.555 diff --git a/test/fixtures/files/domain_versions.csv b/test/fixtures/files/domain_versions.csv new file mode 100644 index 000000000..8fa7fa9fe --- /dev/null +++ b/test/fixtures/files/domain_versions.csv @@ -0,0 +1,3 @@ +Name,Registrant,Registrar,Action,Created at +,test_code,Best Names,update,2018-04-23 15:50:48 +,John,,update,2010-07-04 21:00:00 diff --git a/test/fixtures/files/domains.csv b/test/fixtures/files/domains.csv new file mode 100644 index 000000000..b8261ebc2 --- /dev/null +++ b/test/fixtures/files/domains.csv @@ -0,0 +1,2 @@ +Domain,Registrant,Valid to,Registrar,Created at,Statuses,Contacts code,Force delete date,Force delete data +metro.test,Jack,2010-07-05 00:00:00,Good Names,2010-07-05 07:30:00,[],"[""jack-001"", ""jack-001""]",, diff --git a/test/fixtures/files/invoices.csv b/test/fixtures/files/invoices.csv new file mode 100644 index 000000000..641cfe036 --- /dev/null +++ b/test/fixtures/files/invoices.csv @@ -0,0 +1,3 @@ +Number,Buyer,Due Date,Receipt Date,Issue Date,Total,Currency,Seller Name +2,Best Names,2010-07-06,Unpaid,2010-07-05,16.5,EUR,Seller Ltd +1,Best Names,2010-07-06,2010-07-05,2010-07-05,16.5,EUR,Seller Ltd diff --git a/test/integration/admin_area/account_activities_test.rb b/test/integration/admin_area/account_activities_test.rb index fe84ea88b..09c9e63b8 100644 --- a/test/integration/admin_area/account_activities_test.rb +++ b/test/integration/admin_area/account_activities_test.rb @@ -7,7 +7,7 @@ class AdminAreaAccountActivitiesIntegrationTest < ApplicationSystemTestCase sign_in users(:admin) @original_default_language = Setting.default_language end - + def test_show_account_activities_page account_activities(:one).update(sum: "123.00") visit admin_account_activities_path @@ -19,7 +19,7 @@ class AdminAreaAccountActivitiesIntegrationTest < ApplicationSystemTestCase visit admin_root_path click_link_or_button 'Settings', match: :first find(:xpath, "//ul/li/a[text()='Account activities']").click - + assert has_current_path?(admin_account_activities_path(created_after: 'today')) end diff --git a/test/integration/admin_area/auction_test.rb b/test/integration/admin_area/auction_test.rb new file mode 100644 index 000000000..c51465ab2 --- /dev/null +++ b/test/integration/admin_area/auction_test.rb @@ -0,0 +1,173 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaAuctionIntegrationTest < ApplicationSystemTestCase + setup do + sign_in users(:admin) + @original_default_language = Setting.default_language + end + + def test_should_open_index_page + visit admin_root_path + click_link_or_button 'Settings', match: :first + find(:xpath, "//ul/li/a[text()='Auctions']").click + + assert_text 'Auctions' + end + + def test_search_domains + visit admin_auctions_path + + auction = auctions(:one) + fill_in 'domain_matches', :with => auction.domain + find(:xpath, ".//button[./span[contains(@class, 'glyphicon-search')]]", match: :first).click + + assert_text auction.domain + assert_text 'auto' + assert_text 'no_bids' + end + + def test_filter_no_bids_auction + auction_one = auctions(:one) + auction_two = auctions(:idn) + + visit admin_auctions_path + select "no_bids", :from => "statuses_contains" + find(:xpath, ".//button[./span[contains(@class, 'glyphicon-search')]]", match: :first).click + + assert_text auction_one.domain + assert_text auction_two.domain + end + + def test_manually_create_auction + visit admin_auctions_path + + fill_in 'domain', :with => 'new-awesome-auction.test' + find(:id, "new-auction-btn", match: :first).click + + assert_text 'new-awesome-auction.test' + assert_text 'manual' + assert_text 'started' + end + + def test_manually_create_auction_with_punycode + visit admin_auctions_path + + fill_in 'domain', :with => 'xn--phimtte-10ad.test' + find(:id, "new-auction-btn", match: :first).click + + assert_text 'xn--phimtte-10ad.test' + assert_text 'manual' + assert_text 'started' + end + + def test_raise_error_if_try_to_add_auction_with_invalid_zone + visit admin_auctions_path + + fill_in 'domain', :with => 'new-awesome-auction.chuchacha' + find(:id, "new-auction-btn", match: :first).click + + assert_no_text 'new-awesome-auction.chuchacha' + assert_text 'Cannot generate domain. Reason: invalid format' + end + + def test_raise_error_if_try_to_add_auction_with_invalid_format + visit admin_auctions_path + + fill_in 'domain', :with => '#de$er.test' + find(:id, "new-auction-btn", match: :first).click + + assert_no_text '#de$er.test' + assert_text 'Cannot generate domain. Reason: invalid format' + end + + def test_raise_error_if_try_to_add_same_domain + visit admin_auctions_path + + fill_in 'domain', :with => 'new-awesome-auction.test' + find(:id, "new-auction-btn", match: :first).click + fill_in 'domain', :with => 'new-awesome-auction.test' + find(:id, "new-auction-btn", match: :first).click + + assert_text 'Adding new-awesome-auction.test failed - domain registered or regsitration is blocked' + end + + def test_raise_error_if_try_to_add_registred_domain + visit admin_auctions_path + domain = domains(:shop) + + fill_in 'domain', :with => domain.name + find(:id, "new-auction-btn", match: :first).click + + assert_text "Adding #{domain.name} failed - domain registered or regsitration is blocked" + end + + def test_raise_error_if_try_to_add_blocked_domain + visit admin_auctions_path + domain = blocked_domains(:one) + + fill_in 'domain', :with => domain.name + find(:id, "new-auction-btn", match: :first).click + + assert_text "Adding #{domain.name} failed - domain registered or regsitration is blocked" + end + + def test_raise_error_if_try_to_add_disputed_domain + visit admin_auctions_path + domain = disputes(:active) + + fill_in 'domain', :with => domain.domain_name + find(:id, "new-auction-btn", match: :first).click + + assert_text "Adding #{domain.domain_name} failed - domain registered or regsitration is blocked" + end + + def test_upload_invalid_csv_file + visit admin_auctions_path + + attach_file(:q_file, Rails.root.join('test', 'fixtures', 'files', 'mass_actions', 'invalid_mass_force_delete_list.csv').to_s) + click_link_or_button 'Upload csv' + assert_text "Invalid CSV format. Should be column with 'name' where is the list of name of domains!" + end + + def test_upload_valid_csv_file + visit admin_auctions_path + + attach_file(:q_file, Rails.root.join('test', 'fixtures', 'files', 'auction_domains_list.csv').to_s) + click_link_or_button 'Upload csv' + assert_text "tere.test" + assert_text "chao.test" + end + + def test_upload_valid_csv_file_with_invalid_item + visit admin_auctions_path + + attach_file(:q_file, Rails.root.join('test', 'fixtures', 'files', 'auction_domains_list_with_invalid_item.csv').to_s) + click_link_or_button 'Upload csv' + assert_text "tere.test" + assert_text "chao.test" + assert_text "These domains were ignored: cha.chacha" + end + + def test_should_remove_domain_from_reserved_if_it_added_to_auction + visit admin_auctions_path + domain = reserved_domains(:one) + + fill_in 'domain', :with => domain.name + find(:id, "new-auction-btn", match: :first).click + + assert_text domain.name + assert_text 'manual' + assert_text 'started' + + visit admin_reserved_domains_path + assert_no_text domain.name + end + + def test_should_open_reserved_page_in_modal_window + visit admin_auctions_path + + find(:id, "reserved-modal", match: :first).click + assert_text 'Reserved domains' + end +end diff --git a/test/integration/api/v1/auctions/details_test.rb b/test/integration/api/v1/auctions/details_test.rb index 374051258..f1ab11545 100644 --- a/test/integration/api/v1/auctions/details_test.rb +++ b/test/integration/api/v1/auctions/details_test.rb @@ -20,8 +20,8 @@ class ApiV1AuctionDetailsTest < ActionDispatch::IntegrationTest assert_response :ok assert_equal ({ 'id' => '1b3ee442-e8fe-4922-9492-8fcb9dccc69c', 'domain' => 'auction.test', - 'status' => Auction.statuses[:no_bids] }), ActiveSupport::JSON - .decode(response.body) + 'status' => Auction.statuses[:no_bids], + 'platform' => nil }), ActiveSupport::JSON.decode(response.body) end def test_auction_not_found diff --git a/test/integration/api/v1/auctions/list_test.rb b/test/integration/api/v1/auctions/list_test.rb index ae3f4338f..dcdff5cec 100644 --- a/test/integration/api/v1/auctions/list_test.rb +++ b/test/integration/api/v1/auctions/list_test.rb @@ -15,8 +15,8 @@ class ApiV1AuctionListTest < ActionDispatch::IntegrationTest assert_response :ok assert_equal ([{ 'id' => '1b3ee442-e8fe-4922-9492-8fcb9dccc69c', 'domain' => 'auction.test', - 'status' => Auction.statuses[:started] }]), ActiveSupport::JSON - .decode(response.body) + 'status' => Auction.statuses[:started], + 'platform' => nil }]), ActiveSupport::JSON.decode(response.body) end def test_does_not_return_finished_auctions diff --git a/test/integration/api/v1/auctions/update_test.rb b/test/integration/api/v1/auctions/update_test.rb index 5b00a1052..4e48c0ca5 100644 --- a/test/integration/api/v1/auctions/update_test.rb +++ b/test/integration/api/v1/auctions/update_test.rb @@ -27,8 +27,8 @@ class ApiV1AuctionUpdateTest < ActionDispatch::IntegrationTest assert_response :ok assert_equal ({ 'id' => '1b3ee442-e8fe-4922-9492-8fcb9dccc69c', 'domain' => 'auction.test', - 'status' => Auction.statuses[:awaiting_payment] }), ActiveSupport::JSON - .decode(response.body) + 'status' => Auction.statuses[:awaiting_payment], + 'platform' => nil }), ActiveSupport::JSON.decode(response.body) end def test_marks_as_awaiting_payment diff --git a/test/integration/epp/contact/check/base_test.rb b/test/integration/epp/contact/check/base_test.rb index f1b9f4d16..6ad027fc6 100644 --- a/test/integration/epp/contact/check/base_test.rb +++ b/test/integration/epp/contact/check/base_test.rb @@ -76,7 +76,7 @@ class EppContactCheckBaseTest < EppTestCase response_xml = Nokogiri::XML(response.body) assert_correct_against_schema response_xml assert_equal '0', response_xml.at_xpath('//contact:id', contact: xml_schema)['avail'] - assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text + # assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text end def test_multiple_contacts @@ -127,7 +127,7 @@ class EppContactCheckBaseTest < EppTestCase assert_correct_against_schema response_xml assert_epp_response :completed_successfully assert_equal "#{@contact.registrar.code}:JOHN-001".upcase, response_xml.at_xpath('//contact:id', contact: xml_schema).text - assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text + # assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text end def test_check_contact_without_prefix @@ -154,7 +154,7 @@ class EppContactCheckBaseTest < EppTestCase assert_correct_against_schema response_xml assert_epp_response :completed_successfully assert_equal "#{@contact.registrar.code}:JOHN-001".upcase, response_xml.at_xpath('//contact:id', contact: xml_schema).text - assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text + # assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text end private diff --git a/test/integration/epp/contact/create/base_test.rb b/test/integration/epp/contact/create/base_test.rb index 72d8597c4..ba94fcd6f 100644 --- a/test/integration/epp/contact/create/base_test.rb +++ b/test/integration/epp/contact/create/base_test.rb @@ -142,42 +142,42 @@ class EppContactCreateBaseTest < EppTestCase assert_epp_response :parameter_value_syntax_error end - def test_responces_error_with_email_error - name = 'new' - email = 'new@registrar@test' - phone = '+1.2' + # def test_responces_error_with_email_error + # name = 'new' + # email = 'new@registrar@test' + # phone = '+1.2' - request_xml = <<-XML - - - - - - - #{name} - - #{phone} - #{email} - - - - - any - - - - - XML + # request_xml = <<-XML + # + # + # + # + # + # + # #{name} + # + # #{phone} + # #{email} + # + # + # + # + # any + # + # + # + # + # XML - assert_no_difference 'Contact.count' do - post epp_create_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } - end + # assert_no_difference 'Contact.count' do + # post epp_create_path, params: { frame: request_xml }, + # headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + # end - response_xml = Nokogiri::XML(response.body) - assert_correct_against_schema response_xml - assert_epp_response :parameter_value_syntax_error - end + # response_xml = Nokogiri::XML(response.body) + # assert_correct_against_schema response_xml + # assert_epp_response :parameter_value_syntax_error + # end def test_respects_custom_code name = 'new' diff --git a/test/integration/epp/contact/update/base_test.rb b/test/integration/epp/contact/update/base_test.rb index 364741f0c..0c55c5223 100644 --- a/test/integration/epp/contact/update/base_test.rb +++ b/test/integration/epp/contact/update/base_test.rb @@ -80,6 +80,35 @@ class EppContactUpdateBaseTest < EppTestCase assert_emails 1 end + def test_destroy_old_validation_when_email_is_changed + @contact.verify_email + old_validation_event = @contact.validation_events.first + @contact.update_columns(code: @contact.code.upcase) + + request_xml = <<-XML + + + + + + john-001 + + john-new@inbox.test + + + + + + XML + + post epp_update_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + + assert_raises(ActiveRecord::RecordNotFound) do + ValidationEvent.find(old_validation_event.id) + end + end + def test_skips_notifying_contact_when_email_is_not_changed assert_equal 'john-001', @contact.code assert_equal 'john@inbox.test', @contact.email diff --git a/test/integration/epp/domain/update/base_test.rb b/test/integration/epp/domain/update/base_test.rb index d021b496d..10c92ebc5 100644 --- a/test/integration/epp/domain/update/base_test.rb +++ b/test/integration/epp/domain/update/base_test.rb @@ -717,52 +717,6 @@ class EppDomainUpdateBaseTest < EppTestCase assert_no_emails end - # COMMENT OU REASON: FOR EXPIRED DOMAIN SHOULD NOT SET FD - # def test_makes_update_if_was_forcedelete - # contact = @domain.contacts.first - # contact.update_attribute(:email, '`@outlook.test') - # contact.verify_email - # assert contact.email_verification_failed? - # @domain.reload - # - # assert @domain.force_delete_scheduled? - # - # @domain.update_attribute(:statuses_before_force_delete, nil) - # - # Setting.request_confirmation_on_registrant_change_enabled = true - # new_registrant = contacts(:william).becomes(Registrant) - # assert_not_equal new_registrant, @domain.registrant - # - # request_xml = <<-XML - # - # - # - # - # - # #{@domain.name} - # - # #{new_registrant.code} - # - # - # - # - # - # #{'test' * 2000} - # - # - # - # - # XML - # - # post epp_update_path, params: { frame: request_xml }, - # headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } - # @domain.reload - # - # response_xml = Nokogiri::XML(response.body) - # assert_correct_against_schema response_xml - # assert_epp_response :completed_successfully - # end - def test_clears_force_delete_when_registrar_changed Setting.request_confirmation_on_registrant_change_enabled = true new_registrant = contacts(:william).becomes(Registrant) diff --git a/test/integration/epp/poll_test.rb b/test/integration/epp/poll_test.rb index 5cdb7e524..29c24af26 100644 --- a/test/integration/epp/poll_test.rb +++ b/test/integration/epp/poll_test.rb @@ -7,16 +7,8 @@ class EppPollTest < EppTestCase # Deliberately does not conform to RFC5730, which requires the first notification to be returned def test_return_latest_notification_when_queue_is_not_empty - request_xml = <<-XML - - - - - - - XML - post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + post epp_poll_path, params: { frame: request_req_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } xml_doc = Nokogiri::XML(response.body) assert_epp_response :completed_successfully_ack_to_dequeue @@ -30,17 +22,9 @@ class EppPollTest < EppTestCase version = Version::DomainVersion.last @notification.update(attached_obj_type: 'DomainVersion', attached_obj_id: version.id) - request_xml = <<-XML - - - - - - - XML assert_nothing_raised do - post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + post epp_poll_path, params: { frame: request_req_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } end xml_doc = Nokogiri::XML(response.body) @@ -54,19 +38,11 @@ class EppPollTest < EppTestCase def test_return_action_data_when_present @notification.update!(action: actions(:contact_update)) - request_xml = <<-XML - - - - - - - XML - post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + post epp_poll_path, params: { frame: request_req_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } xml_doc = Nokogiri::XML(response.body) - namespace = Xsd::Schema.filename(for_prefix: 'changePoll') + namespace = Xsd::Schema.filename(for_prefix: 'changePoll', for_version: '1.0') assert_equal 'update', xml_doc.xpath('//changePoll:operation', 'changePoll' => namespace).text assert_equal Time.zone.parse('2010-07-05').utc.xmlschema, xml_doc.xpath('//changePoll:date', 'changePoll' => namespace).text @@ -76,19 +52,35 @@ class EppPollTest < EppTestCase 'changePoll' => namespace).text end + def test_return_notifcation_with_bulk_action_data + bulk_action = actions(:contacts_update_bulk_action) + @notification.update!(action: bulk_action, + attached_obj_id: bulk_action.id, + attached_obj_type: 'BulkAction') + + post epp_poll_path, params: { frame: request_req_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + + xml_doc = Nokogiri::XML(response.body) + namespace = Xsd::Schema.filename(for_prefix: 'changePoll', for_version: '1.0') + + assert_equal 2, xml_doc.xpath('//contact:cd', contact: xml_schema).size + assert_epp_response :completed_successfully_ack_to_dequeue + assert_equal 'bulk_update', xml_doc.xpath('//changePoll:operation', + 'changePoll' => namespace).text + assert_equal @notification.action.id.to_s, xml_doc.xpath('//changePoll:svTRID', + 'changePoll' => namespace).text + assert_equal 'Registrant User', xml_doc.xpath('//changePoll:who', + 'changePoll' => namespace).text + assert_equal 'Auto-update according to official data', + xml_doc.xpath('//changePoll:reason', 'changePoll' => namespace).text + end + def test_no_notifications registrars(:bestnames).notifications.delete_all(:delete_all) - request_xml = <<-XML - - - - - - - XML - post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + post epp_poll_path, params: { frame: request_req_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } assert_epp_response :completed_successfully_no_messages end @@ -106,7 +98,7 @@ class EppPollTest < EppTestCase XML post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } notification.reload xml_doc = Nokogiri::XML(response.body) @@ -128,7 +120,7 @@ class EppPollTest < EppTestCase XML post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } notification.reload assert notification.unread? @@ -145,13 +137,22 @@ class EppPollTest < EppTestCase XML post epp_poll_path, params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } assert_epp_response :object_does_not_exist end def test_anonymous_user_cannot_access - request_xml = <<-XML + post '/epp/command/poll', params: { frame: request_req_xml }, + headers: { 'HTTP_COOKIE' => 'session=non-existent' } + + assert_epp_response :authorization_error + end + + private + + def request_req_xml + <<-XML @@ -159,10 +160,9 @@ class EppPollTest < EppTestCase XML + end - post '/epp/command/poll', params: { frame: request_xml }, - headers: { 'HTTP_COOKIE' => 'session=non-existent' } - - assert_epp_response :authorization_error + def xml_schema + Xsd::Schema.filename(for_prefix: 'contact-ee', for_version: '1.1') end end diff --git a/test/integration/registrant_area/application_helper_test.rb b/test/integration/registrant_area/application_helper_test.rb deleted file mode 100644 index d915baf61..000000000 --- a/test/integration/registrant_area/application_helper_test.rb +++ /dev/null @@ -1,14 +0,0 @@ -require 'test_helper' - -class ApplicationHelperTest < ActionView::TestCase - def test_env_style_when_pic_present - assert_dom_equal %{}, - %{} - end - - def test_env_style_return_nil - env_style = '' - assert_dom_equal %{}, - %{} - end -end diff --git a/test/integration/repp/v1/domains/contacts_test.rb b/test/integration/repp/v1/domains/contacts_test.rb index b9b26a745..17f8f1f6b 100644 --- a/test/integration/repp/v1/domains/contacts_test.rb +++ b/test/integration/repp/v1/domains/contacts_test.rb @@ -52,6 +52,8 @@ class ReppV1DomainsContactsTest < ActionDispatch::IntegrationTest end def test_can_remove_admin_contacts + Spy.on_instance_method(Actions::DomainUpdate, :validate_email).and_return(true) + contact = contacts(:john) payload = { contacts: [ { code: contact.code, type: 'admin' } ] } post "/repp/v1/domains/#{@domain.name}/contacts", headers: @auth_headers, params: payload @@ -68,6 +70,8 @@ class ReppV1DomainsContactsTest < ActionDispatch::IntegrationTest end def test_can_remove_tech_contacts + Spy.on_instance_method(Actions::DomainUpdate, :validate_email).and_return(true) + contact = contacts(:john) payload = { contacts: [ { code: contact.code, type: 'tech' } ] } post "/repp/v1/domains/#{@domain.name}/contacts", headers: @auth_headers, params: payload @@ -77,6 +81,9 @@ class ReppV1DomainsContactsTest < ActionDispatch::IntegrationTest delete "/repp/v1/domains/#{@domain.name}/contacts", headers: @auth_headers, params: payload json = JSON.parse(response.body, symbolize_names: true) + @domain.reload + contact.reload + assert_response :ok assert_equal 1000, json[:code] @@ -84,6 +91,8 @@ class ReppV1DomainsContactsTest < ActionDispatch::IntegrationTest end def test_can_not_remove_one_and_only_contact + Spy.on_instance_method(Actions::DomainUpdate, :validate_email).and_return(true) + contact = @domain.admin_contacts.last payload = { contacts: [ { code: contact.code, type: 'admin' } ] } @@ -96,5 +105,4 @@ class ReppV1DomainsContactsTest < ActionDispatch::IntegrationTest assert @domain.admin_contacts.any? end - end diff --git a/test/interactions/force_delete_email/base_test.rb b/test/interactions/force_delete_email/base_test.rb new file mode 100644 index 000000000..c3f688678 --- /dev/null +++ b/test/interactions/force_delete_email/base_test.rb @@ -0,0 +1,18 @@ +require 'test_helper' + +class BaseTest < ActiveSupport::TestCase + def test_hold_domains_force_delete_email + domain = domains(:shop) + domain.update!(statuses: [DomainStatus::SERVER_HOLD]) + domain.update!(expire_time: Time.zone.now + 1.year) + + registrant = domain.registrant + registrant.update!(email: "#{registrant.email.split('@').first}@#{domain.name}") + + Domains::ForceDeleteEmail::Base.run(email: registrant.email) + + domain.reload + + assert_not domain.force_delete_scheduled? + end +end diff --git a/test/jobs/migrate_before_force_delete_statuses_job_test.rb b/test/jobs/migrate_before_force_delete_statuses_job_test.rb deleted file mode 100644 index 0288a686c..000000000 --- a/test/jobs/migrate_before_force_delete_statuses_job_test.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'test_helper' - -class MigrateBeforeForceDeleteStatusesJobTest < ActiveJob::TestCase - setup do - travel_to Time.zone.parse('2010-07-05') - @domain = domains(:shop) - end - - def test_migrate_data_before_force_delete - @domain.update(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED]) - @domain.reload - assert @domain.statuses.include? DomainStatus::SERVER_UPDATE_PROHIBITED - - @domain.schedule_force_delete(type: :soft) - @domain.reload - - assert @domain.force_delete_scheduled? - - perform_enqueued_jobs do - MigrateBeforeForceDeleteStatusesJob.perform_later - end - - @domain.reload - - assert @domain.force_delete_domain_statuses_history.include? DomainStatus::SERVER_UPDATE_PROHIBITED - end -end diff --git a/test/jobs/migrate_statuses_to_domain_history_job_test.rb b/test/jobs/migrate_statuses_to_domain_history_job_test.rb deleted file mode 100644 index dcacc327a..000000000 --- a/test/jobs/migrate_statuses_to_domain_history_job_test.rb +++ /dev/null @@ -1,22 +0,0 @@ -require 'test_helper' - -class MigrateBeforeForceDeleteStatusesJobTest < ActiveJob::TestCase - setup do - travel_to Time.zone.parse('2010-07-05') - @domain = domains(:shop) - end - - def test_migrate_statuses_to_domain_history_job - @domain.update(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED]) - @domain.reload - assert @domain.statuses.include? DomainStatus::SERVER_UPDATE_PROHIBITED - - perform_enqueued_jobs do - MigrateStatusesToDomainHistoryJob.perform_later - end - - @domain.reload - - assert @domain.admin_store_statuses_history.include? DomainStatus::SERVER_UPDATE_PROHIBITED - end -end diff --git a/test/jobs/nameserver_record_validation_job_test.rb b/test/jobs/nameserver_record_validation_job_test.rb index 1f39c6d33..19d1a2c9e 100644 --- a/test/jobs/nameserver_record_validation_job_test.rb +++ b/test/jobs/nameserver_record_validation_job_test.rb @@ -13,7 +13,8 @@ class NameserverRecordValidationJobTest < ActiveSupport::TestCase def test_nameserver_should_validate_succesfully_and_set_validation_datetime mock_dns_response = OpenStruct.new answer = OpenStruct.new - answer.serial = '12343' + answer.instance_variable_set(:@serial, '12345') + mock_dns_response.answer = [ answer ] Spy.on_instance_method(NameserverValidator, :setup_resolver).and_return(Dnsruby::Resolver.new) @@ -26,6 +27,8 @@ class NameserverRecordValidationJobTest < ActiveSupport::TestCase NameserverRecordValidationJob.perform_now(domain_name: @domain.name) @nameserver.reload + p @nameserver + assert_not_nil @nameserver.validation_datetime assert_nil @nameserver.validation_counter assert_nil @nameserver.failed_validation_reason @@ -47,7 +50,7 @@ class NameserverRecordValidationJobTest < ActiveSupport::TestCase assert_nil @nameserver.validation_datetime assert @nameserver.validation_counter, 1 - assert @nameserver.failed_validation_reason.include? "No any answer comes from **#{@nameserver.hostname}**" + assert @nameserver.failed_validation_reason.include? "DNS Server **#{@nameserver.hostname}**" end def test_should_return_failed_validation_with_serial_reason @@ -68,13 +71,14 @@ class NameserverRecordValidationJobTest < ActiveSupport::TestCase assert_nil @nameserver.validation_datetime assert @nameserver.validation_counter, 1 - assert @nameserver.failed_validation_reason.include? "Serial number for nameserver hostname **#{@nameserver.hostname}** doesn't present. SOA validation failed." + assert @nameserver.failed_validation_reason.include? "Serial number for nameserver hostname **#{@nameserver.hostname}** of #{@nameserver.domain.name} doesn't present in zone. SOA validation failed." end def test_after_third_invalid_times_nameserver_should_be_invalid mock_dns_response = OpenStruct.new answer = OpenStruct.new answer.some_field = '12343' + answer.type = 'SOA' mock_dns_response.answer = [ answer ] Spy.on_instance_method(NameserverValidator, :setup_resolver).and_return(Dnsruby::Resolver.new) @@ -89,9 +93,12 @@ class NameserverRecordValidationJobTest < ActiveSupport::TestCase end @nameserver.reload + + p @nameserver.failed_validation_reason + assert_nil @nameserver.validation_datetime assert @nameserver.validation_counter, 1 - assert @nameserver.failed_validation_reason.include? "Serial number for nameserver hostname **#{@nameserver.hostname}** doesn't present. SOA validation failed." + assert @nameserver.failed_validation_reason.include? "Serial number for nameserver hostname **#{@nameserver.hostname}** of #{@nameserver.domain.name} doesn't present in zone. SOA validation failed." assert @nameserver.failed_validation? end diff --git a/test/lib/serializers/repp/domain_test.rb b/test/lib/serializers/repp/domain_test.rb new file mode 100644 index 000000000..365930278 --- /dev/null +++ b/test/lib/serializers/repp/domain_test.rb @@ -0,0 +1,17 @@ +require 'test_helper' +require 'serializers/repp/domain' + +class SerializersReppDomainTest < ActiveSupport::TestCase + def setup + @domain = domains(:airport) + end + + def test_returns_status_notes + status_notes = { 'serverForceDelete' => '`@internet2.ee' } + @domain.update!(statuses: %w[serverForceDelete], status_notes: status_notes) + @serializer = Serializers::Repp::Domain.new(@domain) + @json = @serializer.to_json + + assert_equal(status_notes, @json[:statuses]) + end +end diff --git a/test/mailers/domain_expire_mailer_test.rb b/test/mailers/domain_expire_mailer_test.rb index ff2d93c79..92d900b42 100644 --- a/test/mailers/domain_expire_mailer_test.rb +++ b/test/mailers/domain_expire_mailer_test.rb @@ -28,33 +28,4 @@ class DomainExpireMailerTest < ActionMailer::TestCase assert_equal I18n.t("domain_expire_mailer.expired_soft.subject", domain_name: domain.name), email.subject end - - # COMMENT OU REASON: FOR EXPIRED DOMAIN SHOULD NOT SET FD - # def test_delivers_domain_expiration_soft_email_if_auto_fd - # domain = domains(:shop) - # email_address = domain.registrar.email - # assert_not domain.force_delete_scheduled? - # travel_to Time.zone.parse('2010-07-05') - # email = '`@internet.ee' - # - # Truemail.configure.default_validation_type = :regex - # - # contact = domain.admin_contacts.first - # contact.update_attribute(:email, email) - # contact.verify_email - # - # assert contact.email_verification_failed? - # - # domain.reload - # - # assert_no domain.force_delete_scheduled? - # - # email = DomainExpireMailer.expired_soft(domain: domain, - # registrar: domain.registrar, - # email: email_address).deliver_now - # - # assert_emails 1 - # assert_equal I18n.t("domain_expire_mailer.expired_soft.subject", domain_name: domain.name), - # email.subject - # end end diff --git a/test/models/bounced_mail_address_test.rb b/test/models/bounced_mail_address_test.rb index 2f266f8bd..b4f2166a0 100644 --- a/test/models/bounced_mail_address_test.rb +++ b/test/models/bounced_mail_address_test.rb @@ -137,9 +137,8 @@ class BouncedMailAddressTest < ActiveSupport::TestCase bounced_mail = BouncedMailAddress.last registrant = domains(:shop).registrant registrant.verify_email(check_level: 'smtp') - + assert_equal registrant.email, bounced_mail.email - assert registrant.email_verification_failed? end def sns_bounce_payload diff --git a/test/models/contact/disclosable_test.rb b/test/models/contact/disclosable_test.rb deleted file mode 100644 index 02adfbb08..000000000 --- a/test/models/contact/disclosable_test.rb +++ /dev/null @@ -1,39 +0,0 @@ -require 'test_helper' - -class ContactDisclosableTest < ActiveSupport::TestCase - setup do - @contact = contacts(:john) - @original_disclosable_attributes = Contact.disclosable_attributes - end - - teardown do - Contact.disclosable_attributes = @original_disclosable_attributes - end - - def test_no_disclosed_attributes_by_default - assert_empty Contact.new.disclosed_attributes - end - - def test_disclosable_attributes - assert_equal %w[name email], Contact.disclosable_attributes - end - - def test_valid_without_disclosed_attributes - @contact.disclosed_attributes = [] - assert @contact.valid? - end - - def test_invalid_when_attribute_is_not_disclosable - Contact.disclosable_attributes = %w[some disclosable] - @contact.disclosed_attributes = %w[some undisclosable] - - assert @contact.invalid? - assert_includes @contact.errors[:disclosed_attributes], 'contain unsupported attribute(s)' - end - - def test_valid_when_attribute_is_disclosable - Contact.disclosable_attributes = %w[some disclosable] - @contact.disclosed_attributes = %w[disclosable] - assert @contact.valid? - end -end diff --git a/test/models/contact_test.rb b/test/models/contact_test.rb index d258d7fb4..59cffee88 100644 --- a/test/models/contact_test.rb +++ b/test/models/contact_test.rb @@ -90,14 +90,14 @@ class ContactTest < ActiveJob::TestCase assert contact.valid? end - def test_email_verification_regex_error - Truemail.configure.default_validation_type = :regex + # def test_email_verification_regex_error + # Truemail.configure.default_validation_type = :regex - contact = valid_contact - contact.email = '`@internet.ee' - assert contact.invalid? - assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_regex_check_error'), contact.errors.messages[:email].first - end + # contact = valid_contact + # contact.email = '`@internet.ee' + # assert contact.invalid? + # assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_regex_check_error'), contact.errors.messages[:email].first + # end def test_invalid_without_phone contact = valid_contact diff --git a/test/models/domain/force_delete_test.rb b/test/models/domain/force_delete_test.rb index f3294f034..48372210b 100644 --- a/test/models/domain/force_delete_test.rb +++ b/test/models/domain/force_delete_test.rb @@ -1,6 +1,8 @@ require 'test_helper' class ForceDeleteTest < ActionMailer::TestCase + include ActiveJob::TestHelper + setup do @domain = domains(:shop) Setting.redemption_grace_period = 30 @@ -356,7 +358,6 @@ class ForceDeleteTest < ActionMailer::TestCase @domain.reload assert @domain.force_delete_scheduled? - assert_equal 'invalid_email', @domain.template_name assert_equal Date.parse('2010-09-19'), @domain.force_delete_date.to_date assert_equal Date.parse('2010-08-05'), @domain.force_delete_start.to_date notification = @domain.registrar.notifications.last @@ -375,7 +376,6 @@ class ForceDeleteTest < ActionMailer::TestCase @domain.reload assert @domain.force_delete_scheduled? - assert_equal 'invalid_email', @domain.template_name assert_equal Date.parse('2010-09-19'), @domain.force_delete_date.to_date assert_equal Date.parse('2010-08-05'), @domain.force_delete_start.to_date notification = @domain.registrar.notifications.last @@ -398,12 +398,10 @@ class ForceDeleteTest < ActionMailer::TestCase contact.verify_email end - assert contact.email_verification_failed? - + perform_check_force_delete_job(contact.id) @domain.reload assert @domain.force_delete_scheduled? - assert_equal 'invalid_email', @domain.template_name assert_equal Date.parse('2010-09-19'), @domain.force_delete_date.to_date assert_equal Date.parse('2010-08-05'), @domain.force_delete_start.to_date assert_equal @domain.status_notes[DomainStatus::FORCE_DELETE], email @@ -411,6 +409,65 @@ class ForceDeleteTest < ActionMailer::TestCase assert notification.text.include? asserted_text end + def test_add_invalid_email_to_domain_status_notes + domain = domains(:airport) + domain.update(valid_to: Time.zone.parse('2012-08-05'), + statuses: %w[serverForceDelete serverRenewProhibited serverTransferProhibited], + force_delete_data: { 'template_name': 'invalid_email', 'force_delete_type': 'soft' }, + status_notes: { "serverForceDelete": '`@internet2.ee' }) + + travel_to Time.zone.parse('2010-07-05') + email = '`@internet.ee' + invalid_emails = '`@internet2.ee `@internet.ee' + asserted_text = "Invalid email: #{invalid_emails}" + + Truemail.configure.default_validation_type = :regex + + contact_first = domain.admin_contacts.first + contact_first.update_attribute(:email_history, 'john@inbox.test') + contact_first.update_attribute(:email, email) + + ValidationEvent::VALID_EVENTS_COUNT_THRESHOLD.times do + contact_first.verify_email + end + + perform_check_force_delete_job(contact_first.id) + domain.reload + + assert_equal domain.status_notes[DomainStatus::FORCE_DELETE], invalid_emails + notification = domain.registrar.notifications.last + assert_not notification.text.include? asserted_text + end + + def test_remove_invalid_email_from_domain_status_notes + domain = domains(:airport) + domain.update(valid_to: Time.zone.parse('2012-08-05'), + statuses: %w[serverForceDelete serverRenewProhibited serverTransferProhibited], + force_delete_data: { 'template_name': 'invalid_email', 'force_delete_type': 'soft' }, + status_notes: { "serverForceDelete": '`@internet2.ee `@internet.ee' }) + + travel_to Time.zone.parse('2010-07-05') + email = '`@internet2.ee' + invalid_email = '`@internet.ee' + asserted_text = "Invalid email: #{invalid_email}" + + Truemail.configure.default_validation_type = :regex + + contact_first = domain.admin_contacts.first + contact_first.update_attribute(:email_history, email) + contact_first.update_attribute(:email, 'john@inbox.test') + + travel_to Time.zone.parse('2010-07-05 0:00:03') + contact_first.verify_email + + perform_check_force_delete_job(contact_first.id) + domain.reload + + assert_equal domain.status_notes[DomainStatus::FORCE_DELETE], invalid_email + notification = domain.registrar.notifications.last + assert notification.text.include? asserted_text + end + def test_domain_should_have_several_bounced_emails @domain.update(valid_to: Time.zone.parse('2012-08-05')) assert_not @domain.force_delete_scheduled? @@ -421,19 +478,20 @@ class ForceDeleteTest < ActionMailer::TestCase contact_one = @domain.admin_contacts.first contact_one.update_attribute(:email, email_one) contact_one.verify_email + perform_check_force_delete_job(contact_one.id) assert contact_one.need_to_start_force_delete? contact_two = @domain.admin_contacts.first contact_two.update_attribute(:email, email_two) contact_two.verify_email + perform_check_force_delete_job(contact_two.id) assert contact_two.need_to_start_force_delete? @domain.reload assert @domain.force_delete_scheduled? - assert_equal 'invalid_email', @domain.template_name assert_equal Date.parse('2010-09-19'), @domain.force_delete_date.to_date assert_equal Date.parse('2010-08-05'), @domain.force_delete_start.to_date assert @domain.status_notes[DomainStatus::FORCE_DELETE].include? email_one @@ -452,13 +510,12 @@ class ForceDeleteTest < ActionMailer::TestCase @domain.reload assert @domain.force_delete_scheduled? - assert_equal 'invalid_email', @domain.template_name assert_equal Date.parse('2010-09-19'), @domain.force_delete_date.to_date assert_equal Date.parse('2010-08-05'), @domain.force_delete_start.to_date notification = @domain.registrar.notifications.last assert notification.text.include? asserted_text - @domain.registrant.update(email: 'aaa@bbb.com') + @domain.registrant.update(email: 'aaa@bbb.com', email_history: email) @domain.registrant.verify_email assert @domain.registrant.need_to_lift_force_delete? CheckForceDeleteLift.perform_now @@ -478,4 +535,12 @@ class ForceDeleteTest < ActionMailer::TestCase @bounced_mail.diagnostic = 'smtp; 550 5.1.1 user unknown' @bounced_mail.save! end + + private + + def perform_check_force_delete_job(contact_id) + perform_enqueued_jobs do + CheckForceDeleteJob.perform_now([contact_id]) + end + end end diff --git a/test/models/registrant_user/registrant_user_creation_test.rb b/test/models/registrant_user/registrant_user_creation_test.rb index 9fff4ca02..a32191db8 100644 --- a/test/models/registrant_user/registrant_user_creation_test.rb +++ b/test/models/registrant_user/registrant_user_creation_test.rb @@ -7,42 +7,26 @@ class RegistrantUserCreationTest < ActiveSupport::TestCase first_name: 'JOHN', last_name: 'SMITH' } - - RegistrantUser.find_or_create_by_api_data(user_data) + assert_difference 'RegistrantUser.count' do + RegistrantUser.find_or_create_by_api_data(user_data) + end user = User.find_by(registrant_ident: 'EE-37710100070') assert_equal('JOHN SMITH', user.username) end - def test_find_or_create_by_api_data_creates_a_user_with_original_name + def test_find_or_create_by_api_data_updates_a_user_with_existing_ident user_data = { - ident: '37710100070', + ident: '1234', + country_code: 'US', first_name: 'John', - last_name: 'Smith' + last_name: 'Smith', } + assert_no_difference 'RegistrantUser.count' do + RegistrantUser.find_or_create_by_api_data(user_data) + end - RegistrantUser.find_or_create_by_api_data(user_data) - - user = User.find_by(registrant_ident: 'EE-37710100070') + user = User.find_by(registrant_ident: 'US-1234') assert_equal('John Smith', user.username) end - - def test_updates_related_contacts_name_if_differs_from_e_identity - contact = contacts(:john) - contact.update(ident: '39708290276', ident_country_code: 'EE') - - user_data = { - ident: '39708290276', - first_name: 'John', - last_name: 'Doe' - } - - RegistrantUser.find_or_create_by_api_data(user_data) - - user = User.find_by(registrant_ident: 'EE-39708290276') - assert_equal('John Doe', user.username) - - contact.reload - assert_equal user.username, contact.name - end end diff --git a/test/models/registrant_user_test.rb b/test/models/registrant_user_test.rb index 987e80c03..81e57fa72 100644 --- a/test/models/registrant_user_test.rb +++ b/test/models/registrant_user_test.rb @@ -32,58 +32,133 @@ class RegistrantUserTest < ActiveSupport::TestCase assert_equal Country.new('US'), user.country end - def test_should_update_org_contact_if_data_from_business_registry_dismatch + def test_should_update_contacts_if_names_dismatch assert_equal 'US-1234', @user.registrant_ident - org = contacts(:acme_ltd) - org.ident_country_code = 'EE' - org.save(validate: false) - org.reload + registrars = [registrars(:bestnames), registrars(:goodnames)] + contacts = [contacts(:john), contacts(:william), contacts(:identical_to_william), + contacts(:acme_ltd), contacts(:registrar_ltd)] + contacts.each do |c| + if c.ident_type == 'priv' + c.ident = @user.ident + else + c.ident_country_code = 'EE' + c.registrar = registrars(:bestnames) + end + c.save(validate: false) + end - company = Company.new(org.ident, "ace") + company_one = Company.new(contacts(:acme_ltd).ident, 'ace') + company_two = Company.new(contacts(:registrar_ltd).ident, 'acer') - company_register = Minitest::Mock.new - company_register.expect(:representation_rights, [company], [{ citizen_personal_code: '1234', - citizen_country_code: 'USA' }]) - @user.companies(company_register) - org.reload + Spy.on(@user, :companies).and_return([company_one, company_two]) + @user.update_contacts - assert_equal org.name, company.company_name + contacts.each do |c| + c.reload + assert_equal @user.username, c.name if c.ident_type == 'priv' + assert @user.actions.find_by(operation: :update, contact_id: c.id) + end + + bulk_action = @user.actions.where(operation: :bulk_update).last + + assert_equal 4, bulk_action.subactions.size + + registrars.each do |r| + notification = r.notifications.unread.order('created_at DESC').take + if r == registrars(:bestnames) + assert_equal '4 contacts have been updated by registrant', notification.text + assert_equal 'BulkAction', notification.attached_obj_type + assert_equal bulk_action.id, notification.attached_obj_id + assert_equal bulk_action.id, notification.action_id + else + assert_equal 'Contact william-002 has been updated by registrant', notification.text + refute notification.action_id + refute notification.attached_obj_id + refute notification.attached_obj_type + end + end end def test_queries_company_register_for_associated_companies assert_equal 'US-1234', @user.registrant_ident - company = Company.new("acme", "ace") + company = Company.new('acme', 'ace') company_register = Minitest::Mock.new company_register.expect(:representation_rights, [company], [{ citizen_personal_code: '1234', - citizen_country_code: 'USA' }]) + citizen_country_code: 'USA' }]) assert_equal [company], @user.companies(company_register) company_register.verify end + def test_should_return_zero_count_of_companies + assert_equal 'US-1234', @user.registrant_ident + contacts = [contacts(:john), contacts(:william), contacts(:identical_to_william), + contacts(:acme_ltd), contacts(:registrar_ltd)] + + contacts.each do |c| + if c.ident_type == 'priv' + c.ident = @user.ident + c.name = @user.username + else + c.ident_country_code = 'EE' + end + c.save(validate: false) + end + + company_one = Company.new(contacts(:acme_ltd).ident, 'Acme Ltd') + company_two = Company.new(contacts(:registrar_ltd).ident, 'Registrar Ltd') + + Spy.on(@user, :companies).and_return([company_one, company_two]) + response = @user.do_need_update_contacts? + + assert_equal response[:counter], 0 + end + + def test_should_return_count_of_contacts_which_should_be_updated + assert_equal 'US-1234', @user.registrant_ident + contacts = [contacts(:john), contacts(:william), contacts(:identical_to_william), + contacts(:acme_ltd), contacts(:registrar_ltd)] + contacts.each do |c| + if c.ident_type == 'priv' + c.ident = @user.ident + else + c.ident_country_code = 'EE' + end + c.save(validate: false) + end + + company_one = Company.new(contacts(:acme_ltd).ident, 'ace') + company_two = Company.new(contacts(:registrar_ltd).ident, 'acer') + + Spy.on(@user, :companies).and_return([company_one, company_two]) + response = @user.do_need_update_contacts? + + assert_equal response[:counter], 5 + end + def test_returns_contacts - Contact.stub(:registrant_user_contacts, %w(john jane)) do - assert_equal %w(john jane), @user.contacts + Contact.stub(:registrant_user_contacts, %w[john jane]) do + assert_equal %w[john jane], @user.contacts end end def test_returns_direct_contacts - Contact.stub(:registrant_user_direct_contacts, %w(john jane)) do - assert_equal %w(john jane), @user.direct_contacts + Contact.stub(:registrant_user_direct_contacts, %w[john jane]) do + assert_equal %w[john jane], @user.direct_contacts end end def test_returns_domains - Domain.stub(:registrant_user_domains, %w(shop airport)) do - assert_equal %w(shop airport), @user.domains + Domain.stub(:registrant_user_domains, %w[shop airport]) do + assert_equal %w[shop airport], @user.domains end end def test_returns_administered_domains - Domain.stub(:registrant_user_administered_domains, %w(shop airport)) do - assert_equal %w(shop airport), @user.administered_domains + Domain.stub(:registrant_user_administered_domains, %w[shop airport]) do + assert_equal %w[shop airport], @user.administered_domains end end end diff --git a/test/models/registrar_test.rb b/test/models/registrar_test.rb index a6b818d35..6dbdff3e8 100644 --- a/test/models/registrar_test.rb +++ b/test/models/registrar_test.rb @@ -48,16 +48,16 @@ class RegistrarTest < ActiveJob::TestCase assert registrar.valid? end - def test_email_verification_regex_error - Truemail.configure.default_validation_type = :regex + # def test_email_verification_regex_error + # Truemail.configure.default_validation_type = :regex - registrar = valid_registrar - registrar.email = '`@internet.ee' - registrar.billing_email = nil + # registrar = valid_registrar + # registrar.email = '`@internet.ee' + # registrar.billing_email = nil - assert registrar.invalid? - assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_regex_check_error'), registrar.errors.messages[:email].first - end + # assert registrar.invalid? + # assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_regex_check_error'), registrar.errors.messages[:email].first + # end def test_billing_email_verification_valid registrar = valid_registrar @@ -66,15 +66,15 @@ class RegistrarTest < ActiveJob::TestCase assert registrar.valid? end - def test_billing_email_verification_regex_error - Truemail.configure.default_validation_type = :regex + # def test_billing_email_verification_regex_error + # Truemail.configure.default_validation_type = :regex - registrar = valid_registrar - registrar.billing_email = '`@strangesentence@internet.ee' + # registrar = valid_registrar + # registrar.billing_email = '`@strangesentence@internet.ee' - assert registrar.invalid? - assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_regex_check_error'), registrar.errors.messages[:billing_email].first - end + # assert registrar.invalid? + # assert_equal I18n.t('activerecord.errors.models.contact.attributes.email.email_regex_check_error'), registrar.errors.messages[:billing_email].first + # end def test_invalid_without_accounting_customer_code registrar = valid_registrar diff --git a/test/system/admin_area/accounts_test.rb b/test/system/admin_area/accounts_test.rb index f07ced9c3..393c3445a 100644 --- a/test/system/admin_area/accounts_test.rb +++ b/test/system/admin_area/accounts_test.rb @@ -29,4 +29,16 @@ class AdminAccountsSystemTest < ApplicationSystemTestCase assert_text 'Account has been successfully updated' assert_text '234' end + + def test_download_accounts_list_as_csv + travel_to Time.zone.parse('2010-07-05 10:30') + + get admin_accounts_path(format: :csv) + + assert_response :ok + assert_equal 'text/csv; charset=utf-8', response.headers['Content-Type'] + assert_equal %(attachment; filename="accounts_#{Time.zone.now.to_formatted_s(:number)}.csv"; filename*=UTF-8''accounts_#{Time.zone.now.to_formatted_s(:number)}.csv), + response.headers['Content-Disposition'] + assert_equal file_fixture('accounts.csv').read, response.body + end end diff --git a/test/system/admin_area/contact_versions_test.rb b/test/system/admin_area/contact_versions_test.rb index f040646bb..e199f5768 100644 --- a/test/system/admin_area/contact_versions_test.rb +++ b/test/system/admin_area/contact_versions_test.rb @@ -62,11 +62,10 @@ class ContactVersionsTest < ApplicationSystemTestCase travel_to now get admin_contact_versions_path(format: :csv) - assert_response :ok assert_equal 'text/csv; charset=utf-8', response.headers['Content-Type'] assert_equal %(attachment; filename="contact_history_#{Time.zone.now.to_formatted_s(:number)}.csv"; filename*=UTF-8''contact_history_#{Time.zone.now.to_formatted_s(:number)}.csv), response.headers['Content-Disposition'] - assert_not_empty response.body + assert_equal file_fixture('contact_versions.csv').read, response.body end end diff --git a/test/system/admin_area/contacts/csv_test.rb b/test/system/admin_area/contacts/csv_test.rb new file mode 100644 index 000000000..de5bd440e --- /dev/null +++ b/test/system/admin_area/contacts/csv_test.rb @@ -0,0 +1,22 @@ +require 'application_system_test_case' + +class ContactsCsvTest < ApplicationSystemTestCase + setup do + sign_in users(:admin) + Domain.destroy_all + Contact.all.each { |contact| contact.destroy unless contact.name == 'Acme Ltd' } + end + + def test_download_contacts_list_as_csv + travel_to Time.zone.parse('2010-07-05 10:30') + contact = Contact.first + contact.created_at = Time.zone.now + contact.save(validate: false) + + visit admin_contacts_url + click_link('CSV') + + assert_equal "attachment; filename=\"contacts_#{Time.zone.now.to_formatted_s(:number)}.csv\"; filename*=UTF-8''contacts_#{Time.zone.now.to_formatted_s(:number)}.csv", response_headers['Content-Disposition'] + assert_equal file_fixture('contacts.csv').read, page.body + end +end diff --git a/test/system/admin_area/domain_versions_test.rb b/test/system/admin_area/domain_versions_test.rb index a8aeb0cd4..75b66b1bb 100644 --- a/test/system/admin_area/domain_versions_test.rb +++ b/test/system/admin_area/domain_versions_test.rb @@ -98,7 +98,7 @@ class DomainVersionsTest < ApplicationSystemTestCase assert_equal 'text/csv; charset=utf-8', response.headers['Content-Type'] assert_equal %(attachment; filename="domain_history_#{Time.zone.now.to_formatted_s(:number)}.csv"; filename*=UTF-8''domain_history_#{Time.zone.now.to_formatted_s(:number)}.csv), response.headers['Content-Disposition'] - assert_not_empty response.body + assert_equal file_fixture('domain_versions.csv').read, response.body end def test_search_event_param diff --git a/test/system/admin_area/domains/csv_test.rb b/test/system/admin_area/domains/csv_test.rb index c84e2cf0e..691a8dc50 100644 --- a/test/system/admin_area/domains/csv_test.rb +++ b/test/system/admin_area/domains/csv_test.rb @@ -1,18 +1,21 @@ require 'application_system_test_case' -class AdminAreaCsvTest < ApplicationSystemTestCase +class DomainsCsvTest < ApplicationSystemTestCase setup do sign_in users(:admin) + Domain.all.each { |domain| domain.destroy unless domain.name == 'metro.test' } end - def test_downloads_domain_list_as_csv - search_params = {"valid_to_lteq"=>nil} - expected_csv = Domain.includes(:registrar, :registrant).search(search_params).result.to_csv - + def test_download_domains_list_as_csv travel_to Time.zone.parse('2010-07-05 10:30') + domain = Domain.first + domain.created_at = Time.zone.now + domain.save(validate: false) + visit admin_domains_url click_link('CSV') + assert_equal "attachment; filename=\"domains_#{Time.zone.now.to_formatted_s(:number)}.csv\"; filename*=UTF-8''domains_#{Time.zone.now.to_formatted_s(:number)}.csv", response_headers['Content-Disposition'] - assert_equal expected_csv, page.body + assert_equal file_fixture('domains.csv').read, page.body end end diff --git a/test/system/admin_area/invoices_test.rb b/test/system/admin_area/invoices_test.rb index 40a50e1c7..a8d0a8a75 100644 --- a/test/system/admin_area/invoices_test.rb +++ b/test/system/admin_area/invoices_test.rb @@ -40,4 +40,14 @@ class AdminAreaInvoicesTest < ApplicationSystemTestCase assert_current_path admin_invoice_path(@invoice) assert_text 'Invoice has been sent' end + + def test_download_invoices_list_as_csv + travel_to Time.zone.parse('2010-07-05 10:30') + + visit admin_invoices_url + click_link('CSV') + + assert_equal "attachment; filename=\"invoices_#{Time.zone.now.to_formatted_s(:number)}.csv\"; filename*=UTF-8''invoices_#{Time.zone.now.to_formatted_s(:number)}.csv", response_headers['Content-Disposition'] + assert_equal file_fixture('invoices.csv').read, page.body + end end diff --git a/test/tasks/check_force_delete_test.rb b/test/tasks/check_force_delete_test.rb new file mode 100644 index 000000000..dbe2f40aa --- /dev/null +++ b/test/tasks/check_force_delete_test.rb @@ -0,0 +1,65 @@ +require 'test_helper' + +class CheckForceDeleteTaskTest < ActiveSupport::TestCase + include ActiveJob::TestHelper + + def setup + @contact = contacts(:john) + @invalid_contact = contacts(:invalid_email) + end + + def test_enque_force_delete_when_three_invalid_records_by_mx + trumail_results = OpenStruct.new(success: false, + email: @contact.email, + domain: 'box.tests', + errors: { mx: 'target host(s) not found' }) + + Spy.on_instance_method(Actions::EmailCheck, :check_email).and_return(trumail_results) + Spy.on_instance_method(Actions::AAndAaaaEmailValidation, :call).and_return([]) + + action = Actions::EmailCheck.new(email: @contact.email, + validation_eventable: @contact, + check_level: 'mx') + 3.times do + action.call + end + + run_task + + assert_enqueued_jobs 1 + assert_enqueued_with(job: CheckForceDeleteJob, args: [[@contact.id]]) + end + + def test_enque_force_delete_when_invalid_record_by_regex + @invalid_contact.verify_email + run_task + + assert_enqueued_jobs 1 + assert_enqueued_with(job: CheckForceDeleteJob, args: [[@invalid_contact.id]]) + end + + def test_not_enque_force_delete + trumail_results = OpenStruct.new(success: false, + email: @contact.email, + domain: 'box.tests', + errors: { mx: 'target host(s) not found' }) + + Spy.on_instance_method(Actions::EmailCheck, :check_email).and_return(trumail_results) + Spy.on_instance_method(Actions::AAndAaaaEmailValidation, :call).and_return([]) + + action = Actions::EmailCheck.new(email: @contact.email, + validation_eventable: @contact, + check_level: 'mx') + 2.times do + action.call + end + + assert_enqueued_jobs 0 + end + + private + + def run_task + Rake::Task['check_force_delete'].execute + end +end