Merge branch 'master' into 2236-removing-old-validation-events

This commit is contained in:
Thiago Youssef 2022-05-17 16:06:41 +03:00
commit bbc1380e46
169 changed files with 2190 additions and 1340 deletions

View file

@ -17,7 +17,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Login to container registry
env:

View file

@ -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

View file

@ -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

1
.gitignore vendored
View file

@ -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.

View file

@ -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)

View file

@ -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'

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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%

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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[:registrant_domains_id_not_null] = 1 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
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

View file

@ -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

View file

@ -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

View file

@ -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]
if !['today', 'tomorrow', 'yesterday'].include?(default_date)
default_date = 'today'
end
default_date = 'today' unless %w[today tomorrow yesterday].include?(default_date)
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

View file

@ -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?

View file

@ -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] ||= {}
if params[:q][:created_at_gteq].nil? && params[:q][:created_at_lteq].nil? && params[:created_after].present?
return unless default_dates?
default_date = params[:created_after]
if !['today', 'tomorrow', 'yesterday'].include?(default_date)
default_date = 'today'
end
default_date = 'today' unless %w[today tomorrow yesterday].include?(default_date)
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

View file

@ -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')
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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -6,18 +6,26 @@ module Domains
end
def notify_without_email
domain.registrar.notifications.create!(text: I18n.t('force_delete_set_on_domain',
template = I18n.t('force_delete_set_on_domain',
domain_name: domain.name,
outzone_date: domain.outzone_date,
purge_date: domain.purge_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',
template = I18n.t('force_delete_auto_email',
domain_name: domain.name,
outzone_date: domain.outzone_date,
purge_date: domain.purge_date,
email: email))
email: email)
return if domain.registrar.notifications.last.text.include? template
domain.registrar.notifications.create!(text: template)
end
end
end

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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
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
end
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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,5 +1,3 @@
module ApiLog
class EppLog < Db
extend ToCsv
end
class EppLog < Db; end
end

View file

@ -1,5 +1,3 @@
module ApiLog
class ReppLog < Db
extend ToCsv
end
class ReppLog < Db; end
end

View file

@ -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

View file

@ -1,6 +1,5 @@
class BlockedDomain < ApplicationRecord
include Versions
extend ToCsv
before_save :generate_data
after_destroy :remove_data

View file

@ -0,0 +1 @@
class BulkAction < Action; end

View file

@ -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

View file

@ -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?

View file

@ -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

View file

@ -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

View file

@ -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']

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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) }

View file

@ -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,
company_register.representation_rights(citizen_personal_code: ident,
citizen_country_code: country.alpha3)
companies = update_contacts_before_receive(companies)
companies
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
contact.save(validate: false)
notify_registrar_data_updated(company_name: company.company_name,
old_contact_name: old_contact_name,
contact: contact)
# 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
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"
)
return [] if contacts.blank?
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

View file

@ -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,9 +218,16 @@ class Registrar < ApplicationRecord
end
def notify(action)
text = I18n.t("notifications.texts.#{action.notification_key}", contact: action.contact.code)
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
iban

View file

@ -1,5 +1,4 @@
class ReservedDomain < ApplicationRecord
extend ToCsv
include Versions # version/reserved_domain_version.rb
include WhoisStatusPopulate
before_save :fill_empty_passwords

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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?

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,15 @@
<div class="modal fade" id="user-form-edit" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Select reserved domains</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<%= render template: 'admin/reserved_domains/index' %>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,155 @@
<div class="page-header">
<h1>Auctions</h1>
</div>
<div class="row">
<div class="col-md-12">
<%= form_with url: admin_auctions_path, method: :get, html: { style: 'margin-bottom: 0;', class: 'js-form', autocomplete: 'off' } do |f| %>
<div class="row">
<div class="col-md-3">
<div class="form-group">
<%= f.label :domain %>
<%= f.search_field :domain_matches, value: params[:domain_matches], class: 'form-control', placeholder: t(:name) %>
</div>
<div class="form-group">
<%= 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' } %>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<%= 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) %>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<%= 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) %>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<%= 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) %>
</div>
</div>
<div class="col-md-4" style="padding-top: 25px; display: flex; flex-direction: row;">
<button class="btn btn-primary" style="margin-right: 10px;">
&nbsp;
<span class="glyphicon glyphicon-search"></span>
&nbsp;
</button>
<div style="margin-right: 10px;">
<%= link_to('Clear', admin_auctions_path, class: 'btn btn-default') %>
</div>
<div style="margin-right: 10px;">
<%= 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' %>
</div>
<div >
<%= link_to "#", class: "btn btn-warning edit", id: 'reserved-modal',
data: {
toggle: "modal",
url: admin_reserved_domains_path,
target: "#user-form-edit"} do %>
<i class="glyphicon glyphicon-menu-right glyphicon-white"></i>
Get reserved domains
<% end %>
<%= render 'modal' %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<hr />
<%= search_form_for [:admin, @q], method: :post, html: { style: 'margin-bottom: 0;', class: 'js-form', autocomplete: 'off' } do |f| %>
<%= label_tag :new_auction %>
<div style="display: flex; flex-direction: row; align-items: center;">
<%= 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' %>
</div>
<% end %>
<hr/>
<div class="row">
<div class="col-md-12" style='margin: 0 0 10px 0; '>
<%= 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 %>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="table-responsive">
<table class="table table-hover table-bordered table-condensed">
<thead>
<tr>
<th class="col-xs-2">
<%= sort_link(@q, 'domain') %>
</th>
<th class="col-xs-2">
<%= sort_link(@q, 'status') %>
</th>
<th class="col-xs-2">
<%= sort_link(@q, 'created_at') %>
</th>
<th class="col-xs-2" style="width: 100px !important; word-break: break-all;">
<%= sort_link(@q, 'registration_code') %>
</th>
<th class="col-xs-2">
<%= sort_link(@q, 'registration_deadline') %>
</th>
<th class="col-xs-1">
<%= sort_link(@q, 'platform', 'Type') %>
</th>
</tr>
</thead>
<tbody>
<% @auctions.each do |auction| %>
<tr>
<td><%= colorize_auction(auction) %></td>
<td><%= auction.status %></td>
<td><%= auction.created_at %></td>
<td style="width: 100px !important; word-break: break-all;"><%= auction.registration_code %></td>
<td><%= auction.registration_deadline %></td>
<td><%= auction.platform.nil? ? 'auto' : auction.platform %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= paginate @auctions %>
</div>
<div class="col-md-6 text-right">
<div class="pagination">
<%= t(:result_count, count: @auctions.total_count) %>
</div>
</div>
</div>
<script>
$('#user-form-edit').on("show.bs.modal", function(e) {
$(this).find('.modal-body').load(e.relatedTarget.dataset.url);
});
</script>

View file

@ -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

View file

@ -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))

View file

@ -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

View file

@ -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'}

View file

@ -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))

View file

@ -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)

View file

@ -9,19 +9,19 @@
<div class="col-md-2">
<div class="form-group">
<%= 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) %>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<%= 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) %>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<%= 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) %>
</div>
</div>
</div>

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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') %>
<div class="row">
<div class="col-md-12">
<%= search_form_for [:admin, @q], html: { style: 'margin-bottom: 0;', class: 'js-form', autocomplete: 'off' } do |f| %>
<div class="row">
<div class="col-md-3">
<div class="form-group">
<%= f.label :name %>
<%= f.search_field :name_matches, value: params[:q][:name_matches], class: 'form-control', placeholder: t(:name) %>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<%= 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) %>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<%= 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) %>
</div>
</div>
</div>
<div class="row">
<div class="col-md-3">
<div class="form-group">
<%= label_tag t(:results_per_page) %>
<%= text_field_tag :results_per_page, params[:results_per_page], class: 'form-control', placeholder: t(:results_per_page) %>
</div>
</div>
<div class="col-md-4" style="padding-top: 25px;">
<button class="btn btn-primary">
&nbsp;
<span class="glyphicon glyphicon-search"></span>
&nbsp;
</button>
<%= 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') %>
</div>
</div>
<% end %>
</div>
</div>
<hr/>
<%= form_for :reserved_elements, url: release_to_auction_admin_reserved_domains_path, html: { class: 'form-horizontal', autocomplete: 'off' } do |f| %>
<div style="display: flex; flex-direction: row; align-items: center">
<%= f.submit 'Send to the auction list', class: 'btn btn-primary', style: 'margin: 10px 0 20px 0;' %>
<span style="margin-left: 10px; font-weight: bold">Domains will be removed from reserved list!</span>
</div>
<div class="row">
<div class="col-md-12">
<div class="table-responsive">
<table class="table table-hover table-bordered table-condensed">
<thead>
<tr>
<th class="col-xs-1 text-center">
<%= check_box_tag :check_all %>
</th>
<th class="col-xs-2">
<%= sort_link(@q, 'name') %>
</th>
<th class="col-xs-2">
<%= sort_link(@q, 'password') %>
</th>
<th class="col-xs-2">
<%= sort_link(@q, 'created_at', t(:created_at)) %>
</th>
<th class="col-xs-2">
<%= sort_link(@q, 'updated_at', t(:updated_at)) %>
</th>
<th class="col-xs-2">
<%= t(:actions) %>
</th>
</tr>
</thead>
<tbody>
<% @domains.each do |x| %>
<tr>
<td class="text-center">
<%= f.check_box :domain_ids, { multiple: true }, x.id, nil %>
</td>
<td>
<%= x.name %>
</td>
<td>
<%= x.password %>
</td>
<td>
<%= l(x.created_at, format: :short) %>
</td>
<td>
<%= l(x.updated_at, format: :short) %>
</td>
<td>
<%= 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') %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
<% end %>
<div class="row">
<div class="col-md-6">
<%= paginate @domains %>
</div>
<div class="col-md-6 text-right">
<div class="pagination">
<%= t(:result_count, count: @domains.total_count) %>
</div>
</div>
</div>
<script>
(function() {
const checkAll = document.getElementById('check_all');
checkAll.addEventListener('click', (source) => {
var checkboxes = document.querySelectorAll('[id^="reserved_elements_domain_ids"]');
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = !checkboxes[i].checked;
}
});
})();
</script>

View file

@ -30,6 +30,7 @@
&nbsp;
= 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)

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

Some files were not shown because too many files have changed in this diff Show more