Strory#108869472 - merge master

This commit is contained in:
Vladimir Krylov 2016-06-10 13:39:36 +03:00
commit f49ee67e83
393 changed files with 5729 additions and 426963 deletions

1
.gitignore vendored
View file

@ -5,6 +5,7 @@ capybara-*.html
/tmp
/db/*.sqlite3
/public/system
/public/assets
/coverage/
/spec/tmp
**.orig

View file

@ -1,3 +1,27 @@
20.05.2016
* Portal for registrars
* domain details view new displays contact name in addition to ID (#117226457)
* added an option to set veryfied = "yes" parameter to GUI for registrant change and domain delete opertions (#116209751)
* Admin interface
* BUG: fixed number of sorting issues on different views (#117350717)
* BUG: internal error on filtered list sorting (#115043065)
* BUG: account activities csv export messes up registrars (#117702653)
* usability fixes to history view (#115762063)
* Registry
* epp-xml gem reference updated to v 1.0.5 (#116209751)
* epp-xml gem is now taken from local repo https://github.com/internetee/epp-xml/blob/master, the version in RubyGems is not updated any more (#116209751)
* BUG: domains set to force delete were deleted a day ahead of time (#117131083)
* BUG: QUE - undefined method `code' for nil:NilClass - if contact is removed before Que gets to it (#117612061)
* BUG: Que - uninitialized constant RegenerateWhoisRecordJob (#117986917)
* EPP
* BUG: poll message on domain delete does not validate against .ee xml schemas (#118827261)
* BUG: internal error on domain delete (#118159567)
* RestWHOIS
* BUG: statuses not in array for not registered reserved and blocked domains (#118911315)
...
21.09.2015
* eis-1.0.xsd schema file updated without a new version, please publish a new updated schema file to public.

13
Gemfile
View file

@ -8,10 +8,11 @@ end if Bundler::VERSION < '2'
source 'https://rubygems.org'
# core
gem 'rails', '4.2.4' # when update, all initializers eis_custom files needs check/update
gem 'rails', '4.2.5.2' # when update, all initializers eis_custom files needs check/update
gem 'iso8601', '0.8.6' # for dates and times
gem 'hashie-forbidden_attributes', '0.1.1'
gem 'SyslogLogger', '2.0', require: 'syslog/logger'
gem 'rest-client'
# load env
gem 'figaro', '1.1.1'
@ -30,17 +31,17 @@ gem 'rails-settings-cached', '0.4.1' # for settings
# html-xml
gem 'haml-rails', '0.9.0' # haml for views
gem 'nokogiri', '1.6.6.2' # For XML parsing
gem 'nokogiri', '1.6.7.2' # For XML parsing
# style
gem 'sass-rails', '5.0.3' # sass style
gem 'bootstrap-sass', '3.3.5.1' # bootstrap style
# js
gem 'uglifier', '2.7.1' # minifies js
gem 'uglifier', '2.7.2' # minifies js
gem 'coffee-rails', '4.1.0' # coffeescript support
gem 'turbolinks', '2.5.3' # faster page load
gem 'jquery-rails', '4.0.3' # jquery
gem 'jquery-rails', '4.0.4' # jquery
gem 'selectize-rails', '0.12.1' # include selectize.js for select
gem 'therubyracer', '0.12.2', platforms: :ruby
gem 'jquery-validation-rails', '1.13.1' # validate on client side
@ -55,7 +56,7 @@ gem 'bootstrap-datepicker-rails', '1.3.1.1' # datepicker
gem 'liquid', '3.0.6' # for email templates
# rights
gem 'devise', '3.5.1' # authenitcation
gem 'devise', '3.5.4' # authenitcation
gem 'cancancan', '1.11.0' # autharization
# rest api
@ -87,7 +88,7 @@ gem 'digidoc_client', '0.2.1'
# epp
gem 'epp', '1.4.2', github: 'internetee/epp'
gem 'epp-xml', '1.0.4' # EIS EPP XMLs
gem 'epp-xml', '1.0.5', github: 'internetee/epp-xml' # EIS EPP XMLs
gem 'uuidtools', '2.1.5' # For unique IDs (used by the epp gem)
# que

View file

@ -16,6 +16,14 @@ GIT
data_migrate (1.3.0)
rails (>= 4.1.0)
GIT
remote: https://github.com/internetee/epp-xml.git
revision: 475f650951f2cf5015e00d48f408a2194ecc1662
specs:
epp-xml (1.0.5)
activesupport (~> 4.1)
builder (~> 3.2)
GIT
remote: https://github.com/internetee/epp.git
revision: 505c3f2739eb1da918e54111aecfb138a822739d
@ -50,38 +58,38 @@ GEM
specs:
SyslogLogger (2.0)
abstract_type (0.0.7)
actionmailer (4.2.4)
actionpack (= 4.2.4)
actionview (= 4.2.4)
activejob (= 4.2.4)
actionmailer (4.2.5.2)
actionpack (= 4.2.5.2)
actionview (= 4.2.5.2)
activejob (= 4.2.5.2)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 1.0, >= 1.0.5)
actionpack (4.2.4)
actionview (= 4.2.4)
activesupport (= 4.2.4)
actionpack (4.2.5.2)
actionview (= 4.2.5.2)
activesupport (= 4.2.5.2)
rack (~> 1.6)
rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (4.2.4)
activesupport (= 4.2.4)
actionview (4.2.5.2)
activesupport (= 4.2.5.2)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
activejob (4.2.4)
activesupport (= 4.2.4)
activejob (4.2.5.2)
activesupport (= 4.2.5.2)
globalid (>= 0.3.0)
activemodel (4.2.4)
activesupport (= 4.2.4)
activemodel (4.2.5.2)
activesupport (= 4.2.5.2)
builder (~> 3.1)
activerecord (4.2.4)
activemodel (= 4.2.4)
activesupport (= 4.2.4)
activerecord (4.2.5.2)
activemodel (= 4.2.5.2)
activesupport (= 4.2.5.2)
arel (~> 6.0)
activerecord-import (0.7.0)
activerecord (>= 3.0)
activesupport (4.2.4)
activesupport (4.2.5.2)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
@ -157,6 +165,7 @@ GEM
concord (0.1.5)
adamantium (~> 0.2.0)
equalizer (~> 0.0.9)
concurrent-ruby (1.0.1)
countries (0.11.4)
currencies (~> 0.4.2)
i18n_data (~> 0.7.0)
@ -173,7 +182,7 @@ GEM
activerecord (>= 3.1.0, < 5.0.0)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
devise (3.5.1)
devise (3.5.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 3.2.6, < 5)
@ -188,9 +197,8 @@ GEM
nokogiri (>= 1.4.0)
savon (>= 2.4.0)
docile (1.1.5)
epp-xml (1.0.4)
activesupport (~> 4.1)
builder (~> 3.2)
domain_name (0.5.25)
unf (>= 0.0.5, < 1.0.0)
equalizer (0.0.11)
erubis (2.7.0)
execjs (2.6.0)
@ -261,6 +269,8 @@ GEM
nokogiri (~> 1.6.0)
ruby_parser (~> 3.5)
html5_validators (1.2.2)
http-cookie (1.0.2)
domain_name (~> 0.5)
httpclient (2.6.0.1)
httpi (2.4.1)
rack
@ -272,7 +282,7 @@ GEM
jbuilder (2.2.16)
activesupport (>= 3.0.0, < 5)
multi_json (~> 1.2)
jquery-rails (4.0.3)
jquery-rails (4.0.4)
rails-dom-testing (~> 1.0)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
@ -302,12 +312,12 @@ GEM
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
method_source (0.8.2)
mime-types (2.6.1)
mime-types (2.99.1)
mina (0.3.1)
open4 (~> 1.3.4)
rake
mini_portile (0.6.2)
minitest (5.8.0)
mini_portile2 (2.0.0)
minitest (5.8.4)
monetize (1.1.0)
money (~> 6.5.0)
money (6.5.1)
@ -320,9 +330,10 @@ GEM
multi_json (1.11.2)
multi_xml (0.5.5)
nenv (0.2.0)
netrc (0.11.0)
newrelic_rpm (3.12.0.288)
nokogiri (1.6.6.2)
mini_portile (~> 0.6.0)
nokogiri (1.6.7.2)
mini_portile2 (~> 2.0.0.rc2)
nori (2.6.0)
notiffany (0.0.7)
nenv (~> 0.1)
@ -365,16 +376,16 @@ GEM
rack-test (0.6.3)
rack (>= 1.0)
railroady (1.3.0)
rails (4.2.4)
actionmailer (= 4.2.4)
actionpack (= 4.2.4)
actionview (= 4.2.4)
activejob (= 4.2.4)
activemodel (= 4.2.4)
activerecord (= 4.2.4)
activesupport (= 4.2.4)
rails (4.2.5.2)
actionmailer (= 4.2.5.2)
actionpack (= 4.2.5.2)
actionview (= 4.2.5.2)
activejob (= 4.2.5.2)
activemodel (= 4.2.5.2)
activerecord (= 4.2.5.2)
activesupport (= 4.2.5.2)
bundler (>= 1.3.0, < 2.0)
railties (= 4.2.4)
railties (= 4.2.5.2)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
@ -382,18 +393,18 @@ GEM
activesupport (>= 4.2.0.beta, < 5.0)
nokogiri (~> 1.6.0)
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.2)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
rails-settings-cached (0.4.1)
rails (>= 4.0.0)
railties (4.2.4)
actionpack (= 4.2.4)
activesupport (= 4.2.4)
railties (4.2.5.2)
actionpack (= 4.2.5.2)
activesupport (= 4.2.5.2)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.0.0)
raindrops (0.15.0)
rake (10.4.2)
rake (10.5.0)
ransack (1.5.1)
actionpack (>= 3.0)
activerecord (>= 3.0)
@ -410,8 +421,12 @@ GEM
unparser (~> 0.2.2)
ref (2.0.0)
request_store (1.1.0)
responders (2.1.0)
railties (>= 4.2.0, < 5)
responders (2.1.1)
railties (>= 4.2.0, < 5.1)
rest-client (1.8.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 3.0)
netrc (~> 0.7)
rspec (3.3.0)
rspec-core (~> 3.3.0)
rspec-expectations (~> 3.3.0)
@ -491,12 +506,13 @@ GEM
spring (1.3.6)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
sprockets (3.3.4)
rack (~> 1.0)
sprockets-rails (2.3.3)
actionpack (>= 3.0)
activesupport (>= 3.0)
sprockets (>= 2.8, < 4.0)
sprockets (3.5.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.0.4)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sys-uname (0.9.0)
ffi (>= 1.0.0)
terminal-table (1.5.2)
@ -512,9 +528,12 @@ GEM
coffee-rails
tzinfo (1.2.2)
thread_safe (~> 0.1)
uglifier (2.7.1)
uglifier (2.7.2)
execjs (>= 0.3.0)
json (>= 1.8.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.1)
unicorn (4.9.0)
kgio (~> 2.6)
rack
@ -536,7 +555,7 @@ GEM
coercible (~> 1.0)
descendants_tracker (~> 0.0, >= 0.0.3)
equalizer (~> 0.0, >= 0.0.9)
warden (1.2.3)
warden (1.2.6)
rack (>= 1.0)
wasabi (3.5.0)
httpi (~> 2.0)
@ -572,10 +591,10 @@ DEPENDENCIES
data_migrate!
database_cleaner (= 1.4.1)
deep_cloneable (= 2.1.1)
devise (= 3.5.1)
devise (= 3.5.4)
digidoc_client (= 0.2.1)
epp (= 1.4.2)!
epp-xml (= 1.0.4)
epp-xml (= 1.0.5)!
fabrication (= 2.13.2)
faker (= 1.4.3)
figaro (= 1.1.1)
@ -591,7 +610,7 @@ DEPENDENCIES
isikukood
iso8601 (= 0.8.6)
jbuilder (= 2.2.16)
jquery-rails (= 4.0.3)
jquery-rails (= 4.0.4)
jquery-ui-rails (= 5.0.5)
jquery-validation-rails (= 1.13.1)
kaminari (= 0.16.3)
@ -600,7 +619,7 @@ DEPENDENCIES
mina (= 0.3.1)
money-rails (= 1.4.1)
newrelic_rpm (= 3.12.0.288)
nokogiri (= 1.6.6.2)
nokogiri (= 1.6.7.2)
nprogress-rails (= 0.1.6.7)
paper_trail!
pdfkit (= 0.6.2)
@ -613,10 +632,11 @@ DEPENDENCIES
que-web (= 0.4.0)
que_mailer!
railroady (= 1.3.0)
rails (= 4.2.4)
rails (= 4.2.5.2)
rails-settings-cached (= 0.4.1)
rake
ransack (= 1.5.1)
rest-client
rspec-rails (= 3.3.2)
rubocop (= 0.32.1)
rubycritic (= 1.4.0)
@ -632,7 +652,7 @@ DEPENDENCIES
therubyracer (= 0.12.2)
traceroute (= 0.5.0)
turbolinks (= 2.5.3)
uglifier (= 2.7.1)
uglifier (= 2.7.2)
unicorn
uuidtools (= 2.1.5)
validates_email_format_of (= 1.6.3)

View file

@ -49,7 +49,8 @@ module Repp
response_code: status,
api_user_name: current_user.try(:username),
api_user_registrar: current_user.try(:registrar).try(:to_s),
ip: request.ip
ip: request.ip,
uuid: request.try(:uuid)
})
end

View file

@ -9,5 +9,6 @@
#= require shared/jquery.validate.bootstrap
#= require jquery-ui/datepicker
#= require select2
#= require jquery.doubleScroll
#= require shared/general
#= require admin/application

View file

@ -16,3 +16,35 @@ $(document).on 'page:change', ->
$(this).validate()
$('[data-toggle="popover"]').popover()
# doublescroll
$('[data-doublescroll]').doubleScroll({
onlyIfScroll: false,
scrollCss:
'overflow-x': 'auto'
'overflow-y': 'hidden'
contentCss:
'overflow-x': 'auto'
'overflow-y': 'hidden'
resetOnWindowResize: true
})
positionSlider = ->
for scroll in document.querySelectorAll('[data-doublescroll]')
wrapper = scroll.previousSibling
if $(scroll).offset().top < $(window).scrollTop()
wrapper.style.position = 'fixed'
wrapper.style.top = '-5px'
else
wrapper.style.position = 'relative'
wrapper.style.top = '0'
return
positionSlider()
$(window).scroll(positionSlider).resize positionSlider
#due .report-table width: auto top scrollbar appears after resize so we do fake resize action
$(window).resize()

View file

@ -27,3 +27,16 @@ $(document).on 'page:change', ->
form.find('.js-ident-tip').show()
$('.js-contact-form').trigger('restoreDefault')
$('[data-legal-document]').each (i, fileInput)->
minSize = 3 * 1024 # 3kB
maxSize = 8 * 1024 * 1024; # 8 MB
$(fileInput).closest('form').submit (e) ->
if (files = fileInput.files).length
fileSize = files[0].size
if fileSize < minSize
alert 'Document size should be more than 3kB'
return false
else if fileSize > maxSize
alert 'Document size should be less than 8MB'
return false

View file

@ -1,8 +1,8 @@
class Admin::AccountActivitiesController < AdminController
load_and_authorize_resource
before_action :set_default_dates, only: [:index]
def index # rubocop: disable Metrics/AbcSize
params[:q] ||= {}
ca_cache = params[:q][:created_at_lteq]
begin
@ -12,11 +12,28 @@ class Admin::AccountActivitiesController < AdminController
logger.warn('Invalid date')
end
balance_params = params[:q].deep_dup
if balance_params[:created_at_gteq]
balance_params.delete('created_at_gteq')
end
@q = AccountActivity.includes(:invoice, account: :registrar).search(params[:q])
@b = AccountActivity.search(balance_params)
@q.sorts = 'id desc' if @q.sorts.empty?
@account_activities = @q.result.page(params[:page]).per(params[:results_per_page])
sort = @account_activities.orders.map(&:to_sql).join(",")
# can do here inline SQL as it's our
if params[:page] && params[:page].to_i > 1
@sum = @q.result.reorder(sort).limit(@account_activities.offset_value).sum(:sum) + @b.result.where("account_activities.id NOT IN (#{@q.result.select(:id).to_sql})").sum(:sum)
else
@sum = @b.result.where("account_activities.id NOT IN (#{@q.result.select(:id).to_sql})").sum(:sum)
end
respond_to do |format|
format.html { @account_activities = @q.result.page(params[:page]) }
format.html
format.csv do
send_data @q.result.to_csv, filename: "account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv"
end
@ -24,4 +41,20 @@ class Admin::AccountActivitiesController < AdminController
params[:q][:created_at_lteq] = ca_cache
end
def set_default_dates
params[:q] ||= {}
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
params[:q][:created_at_gteq] = Date.send(default_date).strftime("%Y-%m-%d")
end
end
end

View file

@ -2,22 +2,54 @@ class Admin::BlockedDomainsController < AdminController
load_and_authorize_resource
def index
bd = BlockedDomain.first_or_initialize
@blocked_domains = bd.names.join("\n")
params[:q] ||= {}
domains = BlockedDomain.all.order(:name)
@q = domains.search(params[:q])
@domains = @q.result.page(params[:page])
@domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i > 0
end
def new
@domain = BlockedDomain.new
end
def create
names = params[:blocked_domains].split("\r\n").map(&:strip)
bd = BlockedDomain.first_or_create
@domain = BlockedDomain.new(blocked_domain_params)
if bd.update(names: names)
flash[:notice] = I18n.t('record_updated')
redirect_to :back
if @domain.save
flash[:notice] = I18n.t('domain_added')
redirect_to admin_blocked_domains_path
else
@blocked_domains = params[:blocked_domains]
flash.now[:alert] = I18n.t('failed_to_update_record')
render :index
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
end
def blocked_domain_params
params.require(:blocked_domain).permit(:name)
end
private
def set_domain
@domain = BlockedDomain.find(params[:id])
end
end

View file

@ -4,20 +4,28 @@ class Admin::ContactsController < AdminController
def index
params[:q] ||= {}
@q = Contact.includes(:registrar).search(params[:q])
@contacts = @q.result.page(params[:page])
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
@q = Contact.includes(:registrar).joins(:registrar).select('contacts.*, registrars.name').search(search_params)
@contacts = @q.result(distinct: :true).page(params[:page])
if params[:statuses_contains]
contacts = Contact.includes(:registrar).where(
contacts = Contact.includes(:registrar).joins(:registrar).select('contacts.*, registrars.name').where(
"contacts.statuses @> ?::varchar[]", "{#{params[:statuses_contains].join(',')}}"
)
else
contacts = Contact.includes(:registrar)
contacts = Contact.includes(:registrar).joins(:registrar).select('contacts.*, registrars.name')
end
contacts = contacts.where("ident_country_code is null or ident_country_code=''") if params[:only_no_country_code].eql?('1')
normalize_search_parameters do
@q = contacts.search(params[:q])
@contacts = @q.result.page(params[:page])
@q = contacts.includes(:registrar).joins(:registrar).select('contacts.*, registrars.name').search(search_params)
@contacts = @q.result.uniq.page(params[:page])
end
@contacts = @contacts.per(params[:results_per_page]) if params[:results_per_page].to_i > 0

View file

@ -9,7 +9,7 @@ class Admin::DomainsController < AdminController
params[:q] ||= {}
if params[:statuses_contains]
domains = Domain.includes(:registrar, :registrant).where(
"statuses @> ?::varchar[]", "{#{params[:statuses_contains].join(',')}}"
"domains.statuses @> ?::varchar[]", "{#{params[:statuses_contains].join(',')}}"
)
else
domains = Domain.includes(:registrar, :registrant)

View file

@ -1,13 +1,33 @@
class Admin::EppLogsController < AdminController
load_and_authorize_resource class: ApiLog::EppLog
before_action :set_default_dates, only: [:index]
def index
@q = ApiLog::EppLog.search(params[:q])
@q.sorts = 'id desc' if @q.sorts.empty?
@epp_logs = @q.result.page(params[:page])
@epp_logs = @q.result
@epp_logs = @epp_logs.where("extract(epoch from created_at) >= extract(epoch from ?::timestamp)", Time.parse(params[:q][:created_at_gteq])) if params[:q][:created_at_gteq].present?
@epp_logs = @epp_logs.where("extract(epoch from created_at) <= extract(epoch from ?::timestamp)", Time.parse(params[:q][:created_at_lteq])) if params[:q][:created_at_lteq].present?
@epp_logs = @epp_logs.page(params[:page])
end
def show
@epp_log = ApiLog::EppLog.find(params[:id])
end
def set_default_dates
params[:q] ||= {}
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
params[:q][:created_at_gteq] = Date.send(default_date).strftime("%Y-%m-%d")
end
end
end

View file

@ -23,7 +23,7 @@ class Admin::InvoicesController < AdminController
def index
@q = Invoice.includes(:account_activity).search(params[:q])
@q.sorts = 'id desc' if @q.sorts.empty?
@q.sorts = 'number desc' if @q.sorts.empty?
@invoices = @q.result.page(params[:page])
end

View file

@ -5,9 +5,7 @@ class Admin::PendingDeletesController < AdminController
def update
authorize! :update, :pending
@epp_domain = Epp::Domain.find(params[:domain_id]) # only epp domain has apply pending
@epp_domain.is_admin= true
if @epp_domain.apply_pending_delete!
if registrant_verification.domain_registrant_delete_confirm!
redirect_to admin_domain_path(@domain.id), notice: t(:pending_applied)
else
redirect_to admin_edit_domain_path(@domain.id), alert: t(:failure)
@ -17,7 +15,7 @@ class Admin::PendingDeletesController < AdminController
def destroy
authorize! :destroy, :pending
if @domain.clean_pendings!
if registrant_verification.domain_registrant_delete_reject!
redirect_to admin_domain_path(@domain.id), notice: t(:pending_removed)
else
redirect_to admin_domain_path(@domain.id), alert: t(:failure)
@ -26,6 +24,14 @@ class Admin::PendingDeletesController < AdminController
private
def registrant_verification
# steal token
token = @domain.registrant_verification_token
@registrant_verification = RegistrantVerification.new(domain_id: @domain.id,
domain_name: @domain.name,
verification_token: token)
end
def find_domain
@domain = Domain.find(params[:domain_id])
end

View file

@ -5,8 +5,7 @@ class Admin::PendingUpdatesController < AdminController
def update
authorize! :update, :pending
@epp_domain = Epp::Domain.find(params[:domain_id]) # only epp domain has apply pending
if @epp_domain.apply_pending_update!
if registrant_verification.domain_registrant_change_confirm!
redirect_to admin_domain_path(@domain.id), notice: t(:pending_applied)
else
redirect_to edit_admin_domain_path(@domain.id), alert: t(:failure)
@ -15,14 +14,21 @@ class Admin::PendingUpdatesController < AdminController
def destroy
authorize! :destroy, :pending
if @domain.clean_pendings!
if registrant_verification.domain_registrant_change_reject!
redirect_to admin_domain_path(@domain.id), notice: t(:pending_removed)
else
redirect_to admin_domain_path(@domain.id), alert: t(:failure)
end
end
def registrant_verification
# steal token
token = @domain.registrant_verification_token
@registrant_verification = RegistrantVerification.new(domain_id: @domain.id,
domain_name: @domain.name,
verification_token: token)
end
private
def find_domain

View file

@ -6,7 +6,7 @@ class Admin::RegistrarsController < AdminController
end
def index
@q = Registrar.ordered.search(params[:q])
@q = Registrar.joins(:accounts).ordered.search(params[:q])
@registrars = @q.result.page(params[:page])
end
@ -57,7 +57,7 @@ class Admin::RegistrarsController < AdminController
def registrar_params
params.require(:registrar).permit(
:name, :reg_no, :vat_no, :street, :city, :state, :zip, :billing_address,
:country_code, :email, :phone, :billing_email, :code
:country_code, :email, :phone, :billing_email, :code, :test_registrar
)
end
end

View file

@ -1,13 +1,34 @@
class Admin::ReppLogsController < AdminController
load_and_authorize_resource class: ApiLog::ReppLog
before_action :set_default_dates, only: [:index]
def index
@q = ApiLog::ReppLog.search(params[:q])
@q.sorts = 'id desc' if @q.sorts.empty?
@repp_logs = @q.result.page(params[:page])
@repp_logs = @q.result
@repp_logs = @repp_logs.where("extract(epoch from created_at) >= extract(epoch from ?::timestamp)", Time.parse(params[:q][:created_at_gteq])) if params[:q][:created_at_gteq].present?
@repp_logs = @repp_logs.where("extract(epoch from created_at) <= extract(epoch from ?::timestamp)", Time.parse(params[:q][:created_at_lteq])) if params[:q][:created_at_lteq].present?
@repp_logs = @repp_logs.page(params[:page])
end
def show
@repp_log = ApiLog::ReppLog.find(params[:id])
end
def set_default_dates
params[:q] ||= {}
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
params[:q][:created_at_gteq] = Date.send(default_date).strftime("%Y-%m-%d")
end
end
end

View file

@ -1,51 +1,68 @@
class Admin::ReservedDomainsController < AdminController
load_and_authorize_resource
before_action :set_domain, only: [:edit, :update]
def index
names = ReservedDomain.pluck(:names).each_with_object({}){|e_h,h| h.merge!(e_h)}
names.names = nil if names.blank?
@reserved_domains = names.to_yaml.gsub(/---.?\n/, '').gsub(/\.\.\..?\n/, '')
params[:q] ||= {}
domains = ReservedDomain.all.order(:name)
@q = domains.search(params[:q])
@domains = @q.result.page(params[:page])
@domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i > 0
end
def new
@domain = ReservedDomain.new
end
def edit
end
def create
@reserved_domains = params[:reserved_domains]
begin
params[:reserved_domains] = "---\n" if params[:reserved_domains].blank?
names = YAML.load(params[:reserved_domains])
fail if names == false
rescue
flash.now[:alert] = I18n.t('invalid_yaml')
logger.warn 'Invalid YAML'
render :index and return
end
@domain = ReservedDomain.new(reserved_domain_params)
result = true
ReservedDomain.transaction do
# removing old ones
existing = ReservedDomain.any_of_domains(names.keys).pluck(:id)
ReservedDomain.where.not(id: existing).delete_all
#updating and adding
names.each do |name, psw|
rec = ReservedDomain.by_domain(name).first
rec ||= ReservedDomain.new
rec.names = {name => psw}
unless rec.save
result = false
raise ActiveRecord::Rollback
end
end
end
if result
flash[:notice] = I18n.t('record_updated')
redirect_to :back
if @domain.save
flash[:notice] = I18n.t('domain_added')
redirect_to admin_reserved_domains_path
else
flash.now[:alert] = I18n.t('failed_to_update_record')
render :index
end
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'
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
end
private
def reserved_domain_params
params.require(:reserved_domain).permit(:name, :password)
end
def set_domain
@domain = ReservedDomain.find(params[:id])
end
end

View file

@ -59,6 +59,7 @@ class Admin::SettingsController < AdminController
:transfer_wait_time,
:invoice_number_min,
:invoice_number_max,
:days_to_keep_business_registry_cache,
:days_to_keep_invoices_active,
:days_to_keep_overdue_invoices_active,
:days_to_renew_domain_before_expire,

View file

@ -32,7 +32,7 @@ class ApplicationController < ActionController::Base
if registrar_request?
registrar_root_url
elsif registrant_request?
registrant_root_url
registrant_login_url
elsif admin_request?
admin_root_url
end
@ -55,6 +55,10 @@ class ApplicationController < ActionController::Base
end
end
def info_for_paper_trail
{ uuid: request.uuid }
end
def user_for_paper_trail
user_log_str(current_user)
end
@ -67,8 +71,7 @@ class ApplicationController < ActionController::Base
end
def user_log_str(user)
return 'public' if user.nil?
"#{user.id}-#{user.class}: #{user.username}"
user.nil? ? 'public' : user.id_role_username
end
def comma_support_for(parent_key, key)

View file

@ -19,6 +19,8 @@ class Epp::ContactsController < EppController
authorize! :create, Epp::Contact
@contact = Epp::Contact.new(params[:parsed_frame], current_user.registrar)
@contact.add_legal_file_to_new(params[:parsed_frame])
if @contact.save
render_epp_response '/epp/contacts/create'
else
@ -29,7 +31,7 @@ class Epp::ContactsController < EppController
def update
authorize! :update, @contact, @password
if @contact.update_attributes(params[:parsed_frame])
if @contact.update_attributes(params[:parsed_frame], current_user)
render_epp_response 'epp/contacts/update'
else
handle_errors(@contact)
@ -39,7 +41,7 @@ class Epp::ContactsController < EppController
def delete
authorize! :delete, @contact, @password
if @contact.destroy_and_clean
if @contact.destroy_and_clean(params[:parsed_frame])
render_epp_response '/epp/contacts/delete'
else
handle_errors(@contact)

View file

@ -29,12 +29,9 @@ class Epp::DomainsController < EppController
handle_errors(@domain) and return if @domain.errors.any?
handle_errors and return unless balance_ok?('create') # loads pricelist in this method
if !@domain_pricelist.try(:price)#checking if pricelist is not found
@domain.add_epp_error('2306', nil, nil, 'No price list for domain')
handle_errors(@domain) and return if @domain.errors.any?
end
ActiveRecord::Base.transaction do
@domain.add_legal_file_to_new(params[:parsed_frame])
if @domain.save # TODO: Maybe use validate: false here because we have already validated the domain?
current_user.registrar.debit!({
sum: @domain_pricelist.price.amount,
@ -107,10 +104,6 @@ class Epp::DomainsController < EppController
period_unit = Epp::Domain.parse_period_unit_from_frame(params[:parsed_frame]) || 'y'
balance_ok?('renew', period, period_unit) # loading pricelist
if !@domain_pricelist.try(:price)#checking if pricelist is not found
@domain.add_epp_error('2306', nil, nil, 'No price list for domain')
handle_errors(@domain) and return if @domain.errors.any?
end
ActiveRecord::Base.transaction do
success = @domain.renew(
@ -258,12 +251,19 @@ class Epp::DomainsController < EppController
def balance_ok?(operation, period = nil, unit = nil)
@domain_pricelist = @domain.pricelist(operation, period.try(:to_i), unit)
if @domain_pricelist.try(:price) # checking if price list is not found
if current_user.registrar.balance < @domain_pricelist.price.amount
epp_errors << {
code: '2104',
msg: I18n.t('billing_failure_credit_balance_low')
}
return false
end
else
epp_errors << {
code: '2104',
msg: I18n.t(:active_price_missing_for_this_operation)
}
return false
end
true

View file

@ -361,16 +361,18 @@ class EppController < ApplicationController
if request_command == 'login' && frame.present?
frame.gsub!(/pw>.+<\//, 'pw>[FILTERED]</')
end
trimmed_request = frame.gsub(/<eis:legalDocument([^>]+)>([^<])+<\/eis:legalDocument>/, "<eis:legalDocument>[FILTERED]</eis:legalDocument>") if frame.present?
ApiLog::EppLog.create({
request: frame,
request: trimmed_request,
request_command: request_command,
request_successful: epp_errors.empty?,
request_object: params[:epp_object_type],
response: @response,
api_user_name: @api_user.try(:username) || current_user.try(:username) || 'api-public',
api_user_registrar: @api_user.try(:registrar).try(:to_s) || current_user.try(:registrar).try(:to_s),
ip: request.ip
ip: request.ip,
uuid: request.uuid
})
end
# rubocop: enable Metrics/CyclomaticComplexity

View file

@ -0,0 +1,26 @@
class Registrant::ContactsController < RegistrantController
helper_method :domain_ids
def show
@contact = Contact.where(id: contacts).find_by(id: params[:id])
@current_user = current_user
authorize! :read, @contact
end
def contacts
begin
DomainContact.where(domain_id: domain_ids).pluck(:contact_id) | Domain.where(id: domain_ids).pluck(:registrant_id)
rescue Soap::Arireg::NotAvailableError => error
flash[:notice] = I18n.t(error.json[:message])
Rails.logger.fatal("[EXCEPTION] #{error.to_s}")
[]
end
end
def domain_ids
@domain_ids ||= begin
ident_cc, ident = @current_user.registrant_ident.to_s.split '-'
BusinessRegistryCache.fetch_by_ident_and_cc(ident, ident_cc).associated_domain_ids
end
end
end

View file

@ -22,18 +22,18 @@ class Registrant::DomainDeleteConfirmsController < RegistrantController
verification_token: params[:token])
if params[:rejected]
if @registrant_verification.domain_registrant_delete_reject!
flash[:notice] = t(:registrant_domain_verification_rejected)
flash[:notice] = t(:registrant_domain_delete_rejected)
redirect_to registrant_domain_delete_confirm_path(@domain.id, rejected: true)
else
flash[:alert] = t(:registrant_domain_verification_rejected_failed)
flash[:alert] = t(:registrant_domain_delete_rejected_failed)
return render 'show'
end
elsif params[:confirmed]
if @registrant_verification.domain_registrant_delete_confirm!
flash[:notice] = t(:registrant_domain_verification_confirmed)
flash[:notice] = t(:registrant_domain_delete_confirmed)
redirect_to registrant_domain_delete_confirm_path(@domain.id, confirmed: true)
else
flash[:alert] = t(:registrant_domain_verification_confirmed_failed)
flash[:alert] = t(:registrant_domain_delete_confirmed_failed)
return render 'show'
end
end

View file

@ -1,5 +1,86 @@
class Registrant::DomainsController < RegistrantController
def index
authorize! :view, :registrant_domains
params[:q] ||= {}
normalize_search_parameters do
@q = domains.search(params[:q])
@domains = @q.result.page(params[:page])
end
@domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i > 0
end
def show
@domain = domains.find(params[:id])
authorize! :read, @domain
end
def set_domain
@domain = domains.find(params[:id])
end
def domain_verification_url
authorize! :view, :registrant_domains
dom = domains.find(params[:id])
if (dom.statuses.include?(DomainStatus::PENDING_UPDATE) || dom.statuses.include?(DomainStatus::PENDING_DELETE_CONFIRMATION)) &&
dom.pending_json.present?
@domain = dom
confirm_path = get_confirm_path(dom.statuses)
@verification_url = "#{confirm_path}/#{@domain.id}?token=#{@domain.registrant_verification_token}"
else
flash[:warning] = I18n.t('available_verification_url_not_found')
redirect_to registrant_domain_path(dom.id)
end
end
def download_list
authorize! :view, :registrant_domains
params[:q] ||= {}
normalize_search_parameters do
@q = domains.search(params[:q])
@domains = @q
end
respond_to do |format|
format.csv { render text: @domains.result.to_csv }
format.pdf do
pdf = @domains.result.pdf(render_to_string('registrant/domains/download_list', layout: false))
send_data pdf, filename: 'domains.pdf'
end
end
end
def domains
ident_cc, ident = @current_user.registrant_ident.split '-'
begin
BusinessRegistryCache.fetch_associated_domains ident, ident_cc
rescue Soap::Arireg::NotAvailableError => error
flash[:notice] = I18n.t(error.json[:message])
Rails.logger.fatal("[EXCEPTION] #{error.to_s}")
current_user.domains
end
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
def get_confirm_path(statuses)
if statuses.include?(DomainStatus::PENDING_UPDATE)
"#{ENV['registrant_url']}/registrant/domain_update_confirms"
elsif statuses.include?(DomainStatus::PENDING_DELETE_CONFIRMATION)
"#{ENV['registrant_url']}/registrant/domain_delete_confirms"
end
end
end

View file

@ -0,0 +1,7 @@
class Registrant::RegistrarsController < RegistrantController
def show
@registrar = Registrar.find(params[:id])
authorize! :read, @registrar
end
end

View file

@ -6,15 +6,10 @@ class Registrant::SessionsController < Devise::SessionsController
# rubocop: disable Metrics/AbcSize
def id
if Rails.env.development?
sign_in(RegistrantUser.find_or_create_by_idc_data('test'), event: :authentication)
return redirect_to registrant_root_url
end
id_code, id_issuer = request.env['SSL_CLIENT_S_DN'], request.env['SSL_CLIENT_I_DN_O']
id_code, id_issuer = 'test', RegistrantUser::ACCEPTED_ISSUER if Rails.env.development?
logger.error request.env['SSL_CLIENT_S_DN']
logger.error request.env['SSL_CLIENT_S_DN'].encoding
logger.error request.env['SSL_CLIENT_I_DN_O']
@user = RegistrantUser.find_or_create_by_idc_data(request.env['SSL_CLIENT_S_DN'], request.env['SSL_CLIENT_I_DN_O'])
@user = RegistrantUser.find_or_create_by_idc_data(id_code, id_issuer)
if @user
sign_in(@user, event: :authentication)
redirect_to registrant_root_url

View file

@ -1,5 +1,9 @@
class Registrant::WhoisController < RegistrantController
def index
authorize! :view, :registrant_whois
if params[:domain_name].present?
@domain = WhoisRecord.find_by(name: params[:domain_name]);
end
end
end

View file

@ -3,18 +3,68 @@ class Registrar::ContactsController < Registrar::DeppController # EPP controller
def index
authorize! :view, Depp::Contact
limit, offset = pagination_details
res = depp_current_user.repp_request('contacts', { details: true, limit: limit, offset: offset })
if res.code == '200'
@response = res.parsed_body.with_indifferent_access
@contacts = @response ? @response[:contacts] : []
params[:q] ||= {}
params[:q].delete_if { |_k, v| v.blank? }
@paginatable_array = Kaminari.paginate_array(
[], total_count: @response[:total_number_of_records]
).page(params[:page]).per(limit)
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
flash.now[:epp_results] = [{ 'code' => res.code, 'msg' => res.message }]
if search_params.length == 1 && search_params[:name_matches].present?
@contacts = Contact.find_by(name: search_params[:name_matches])
end
if params[:statuses_contains]
contacts = current_user.registrar.contacts.includes(:registrar).where(
"contacts.statuses @> ?::varchar[]", "{#{params[:statuses_contains].join(',')}}"
)
else
contacts = current_user.registrar.contacts.includes(:registrar)
end
normalize_search_parameters do
@q = contacts.search(search_params)
@contacts = @q.result(distinct: :true).page(params[:page])
end
@contacts = @contacts.per(params[:results_per_page]) if params[:results_per_page].to_i > 0
end
def download_list
authorize! :view, Depp::Contact
params[:q] ||= {}
params[:q].delete_if { |_k, v| v.blank? }
if params[:q].length == 1 && params[:q][:name_matches].present?
@contacts = Contact.find_by(name: params[:q][:name_matches])
end
if params[:statuses_contains]
contacts = current_user.registrar.contacts.includes(:registrar).where(
"contacts.statuses @> ?::varchar[]", "{#{params[:statuses_contains].join(',')}}"
)
else
contacts = current_user.registrar.contacts.includes(:registrar)
end
normalize_search_parameters do
@q = contacts.search(params[:q])
@contacts = @q.result.page(params[:page])
end
@contacts = @contacts.per(params[:results_per_page]) if params[:results_per_page].to_i > 0
respond_to do |format|
format.csv { render text: @contacts.to_csv }
format.pdf do
pdf = @contacts.pdf(render_to_string('registrar/contacts/download_list', layout: false))
send_data pdf, filename: 'contacts.pdf'
end
end
end
def new
@ -75,4 +125,18 @@ class Registrar::ContactsController < Registrar::DeppController # EPP controller
def init_epp_contact
Depp::Contact.user = depp_current_user
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

View file

@ -72,4 +72,15 @@ module ApplicationHelper
link_to(title, url_for(sort: {param_name => order}), class: "sort_link #{order}")
end
def changing_css_class(version, *attrs)
return unless version
css_class = "text-warning"
if attrs.size == 1
version.object_changes.to_h[attrs.first] && css_class
else
version.object_changes.to_h.slice(*attrs).any? && css_class
end
end
end

View file

@ -3,17 +3,30 @@ class DomainDeleteConfirmJob < Que::Job
# it's recommended to keep transaction against job table as short as possible.
ActiveRecord::Base.transaction do
domain = Epp::Domain.find(domain_id)
case action
when RegistrantVerification::CONFIRMED
domain.poll_message!(:poll_pending_delete_confirmed_by_registrant)
domain.apply_pending_delete!
raise_errors!(domain)
when RegistrantVerification::REJECTED
DomainMailer.pending_delete_rejected_notification(domain_id, true).deliver
domain.statuses.delete(DomainStatus::PENDING_DELETE_CONFIRMATION)
domain.poll_message!(:poll_pending_delete_rejected_by_registrant)
domain.cancel_pending_delete
domain.save(validate: false)
raise_errors!(domain)
DomainMailer.pending_delete_rejected_notification(domain_id, true).deliver
end
destroy # it's best to destroy the job in the same transaction
end
end
def raise_errors!(domain)
throw "domain #{domain.name} failed with errors #{domain.errors.full_messages}" if domain.errors.any?
end
end

View file

@ -0,0 +1,17 @@
class DomainDeleteJob < Que::Job
def run(domain_id)
domain = Domain.find(domain_id)
::PaperTrail.whodunnit = "job - #{self.class.name}"
WhoisRecord.where(domain_id: domain.id).destroy_all
domain.destroy
bye_bye = domain.versions.last
domain.registrar.messages.create!(
body: "#{I18n.t(:domain_deleted)}: #{domain.name}",
attached_obj_id: bye_bye.id,
attached_obj_type: bye_bye.class.to_s
)
end
end

View file

@ -0,0 +1,10 @@
class DomainSetDeleteCandidateJob < Que::Job
def run(domain_id)
domain = Domain.find(domain_id)
domain.statuses << DomainStatus::DELETE_CANDIDATE
::PaperTrail.whodunnit = "job - #{self.class.name}"
domain.save(validate: false)
DomainDeleteJob.enqueue(domain.id, run_at: rand(((24*60) - (DateTime.now.hour * 60 + DateTime.now.minute))).minutes.from_now)
end
end

View file

@ -3,21 +3,27 @@ class DomainUpdateConfirmJob < Que::Job
# it's recommended to keep transaction against job table as short as possible.
ActiveRecord::Base.transaction do
domain = Epp::Domain.find(domain_id)
domain.is_admin = true
case action
when RegistrantVerification::CONFIRMED
domain.poll_message!(:poll_pending_update_confirmed_by_registrant)
domain.apply_pending_update! do |e|
e.instance_variable_set("@changed_attributes", e.changed_attributes.merge("statuses"=>[]))
end
raise_errors!(domain)
domain.apply_pending_update!
raise_errors!(domain)
domain.clean_pendings!
raise_errors!(domain)
when RegistrantVerification::REJECTED
DomainMailer.pending_update_rejected_notification_for_new_registrant(domain_id).deliver
domain.send_mail :pending_update_rejected_notification_for_new_registrant
domain.poll_message!(:poll_pending_update_rejected_by_registrant)
domain.clean_pendings!
domain.instance_variable_set("@changed_attributes", domain.changed_attributes.merge("statuses"=>[]))
domain.save
domain.clean_pendings_lowlevel
end
destroy # it's best to destroy the job in the same transaction
end
end
def raise_errors!(domain)
throw "domain #{domain.name} failed with errors #{domain.errors.full_messages}" if domain.errors.any?
end
end

View file

@ -3,8 +3,8 @@ class RegenerateRegistrarWhoisesJob < Que::Job
# no return as we want restart job if fails
registrar = Registrar.find(registrar_id)
registrar.whois_records.select(:id).find_in_batches(batch_size: 20) do |group|
RegenerateWhoisRecordJob.enqueue group.map(&:id)
registrar.whois_records.select(:name).find_in_batches(batch_size: 20) do |group|
UpdateWhoisRecordJob.enqueue group.map(&:name), 'domain'
end
end
end

View file

@ -1,10 +0,0 @@
class RegenerateWhoisRecordJob < Que::Job
def run(ids)
ids.each do |id|
record = WhoisRecord.find_by(id: id)
return unless record
record.save
end
end
end

View file

@ -0,0 +1,52 @@
class UpdateWhoisRecordJob < Que::Job
def run(names, type)
klass = case type
when 'reserved'then ReservedDomain
when 'blocked' then BlockedDomain
when 'domain' then Domain
end
Array(names).each do |name|
record = klass.find_by(name: name)
if record
send "update_#{type}", record
else
send "delete_#{type}", name
end
end
end
def update_domain(domain)
domain.whois_record ? domain.whois_record.save : domain.create_whois_record
end
def update_reserved(record)
record.generate_data
end
def update_blocked(record)
update_reserved(record)
end
# 1. deleting own
# 2. trying to regenerate reserved in order domain is still in the list
def delete_domain(name)
WhoisRecord.where(name: name).destroy_all
BlockedDomain.find_by(name: name).try(:generate_data)
ReservedDomain.find_by(name: name).try(:generate_data)
end
def delete_reserved(name)
Domain.where(name: name).any?
Whois::Record.where(name: name).delete_all
end
def delete_blocked(name)
delete_reserved(name)
end
end

View file

@ -4,6 +4,11 @@ class ContactMailer < ApplicationMailer
def email_updated(old_email, email, contact_id, should_deliver)
@contact = Contact.find_by(id: contact_id)
@old_email = old_email
unless @contact
Rails.logger.info "Cannot send email in #{self.class.name}##{__method__} with contact_id #{contact_id}. It cannot be found"
return
end
return unless email || @contact
return if delivery_off?(@contact, should_deliver)

View file

@ -1,109 +1,50 @@
class DomainMailer < ApplicationMailer
include Que::Mailer
def pending_update_request_for_old_registrant(domain_id, old_registrant_id, should_deliver)
def pending_update_request_for_old_registrant(params)
compose_from(params)
end
def pending_update_notification_for_new_registrant(params)
compose_from(params)
end
def registrant_updated_notification_for_new_registrant(domain_id, old_registrant_id, new_registrant_id, should_deliver)
@domain = Domain.find_by(id: domain_id)
@old_registrant = Registrant.find(old_registrant_id)
return unless @domain
return if delivery_off?(@domain, should_deliver)
if @domain.registrant_verification_token.blank?
logger.warn "EMAIL NOT DELIVERED: registrant_verification_token is missing for #{@domain.name}"
return
end
if @domain.registrant_verification_asked_at.blank?
logger.warn "EMAIL NOT DELIVERED: registrant_verification_asked_at is missing for #{@domain.name}"
return
end
confirm_path = "#{ENV['registrant_url']}/registrant/domain_update_confirms"
@verification_url = "#{confirm_path}/#{@domain.id}?token=#{@domain.registrant_verification_token}"
return if whitelist_blocked?(@old_registrant.email)
mail(to: format(@old_registrant.email),
subject: "#{I18n.t(:pending_update_request_for_old_registrant_subject,
name: @domain.name)} [#{@domain.name}]")
end
def pending_update_notification_for_new_registrant(domain_id, old_registrant_id, should_deliver)
@domain = Domain.find_by(id: domain_id)
@old_registrant = Registrant.find(old_registrant_id)
return unless @domain
return if delivery_off?(@domain, should_deliver)
if @domain.registrant_verification_token.blank?
logger.warn "EMAIL NOT DELIVERED: registrant_verification_token is missing for #{@domain.name}"
return
end
if @domain.registrant_verification_asked_at.blank?
logger.warn "EMAIL NOT DELIVERED: registrant_verification_asked_at is missing for #{@domain.name}"
return
end
@new_registrant = @domain.registrant # NB! new registrant at this point
@new_registrant = Registrant.find(new_registrant_id)
return if whitelist_blocked?(@new_registrant.email)
mail(to: format(@new_registrant.email),
subject: "#{I18n.t(:pending_update_notification_for_new_registrant_subject,
name: @domain.name)} [#{@domain.name}]")
end
def registrant_updated_notification_for_new_registrant(domain_id, should_deliver)
@domain = Domain.find_by(id: domain_id)
return unless @domain
return if delivery_off?(@domain, should_deliver)
return if whitelist_blocked?(@domain.registrant_email)
mail(to: format(@domain.registrant_email),
subject: "#{I18n.t(:registrant_updated_notification_for_new_registrant_subject,
name: @domain.name)} [#{@domain.name}]")
end
def registrant_updated_notification_for_old_registrant(domain_id, should_deliver)
domain = Domain.find_by(id: domain_id)
return unless domain
def registrant_updated_notification_for_old_registrant(domain_id, old_registrant_id, new_registrant_id, should_deliver)
@domain = Domain.find_by(id: domain_id)
return unless @domain
return if delivery_off?(@domain, should_deliver)
@old_registrant_email = domain.registrant_email # Nb! before applying pending updates
@old_registrant = Registrant.find(old_registrant_id)
@new_registrant = Registrant.find(new_registrant_id)
return if whitelist_blocked?(@old_registrant_email)
mail(to: format(@old_registrant_email),
return if whitelist_blocked?(@old_registrant.email)
mail(to: format(@old_registrant.email),
subject: "#{I18n.t(:registrant_updated_notification_for_old_registrant_subject,
name: @domain.name)} [#{@domain.name}]")
end
def pending_update_rejected_notification_for_new_registrant(domain_id)
@domain = Domain.find_by(id: domain_id)
return unless @domain
# no delivery off control, driggered by que, no epp request
@new_registrant_email = @domain.pending_json['new_registrant_email']
@new_registrant_name = @domain.pending_json['new_registrant_name']
return if whitelist_blocked?(@new_registrant_email)
mail(to: format(@new_registrant_email),
subject: "#{I18n.t(:pending_update_rejected_notification_for_new_registrant_subject,
name: @domain.name)} [#{@domain.name}]")
def pending_update_rejected_notification_for_new_registrant(params)
compose_from(params)
end
def pending_update_expired_notification_for_new_registrant(domain_id)
@domain = Domain.find_by(id: domain_id)
return unless @domain
# no delivery off control, driggered by cron, no epp request
@new_registrant_email = @domain.pending_json['new_registrant_email']
@new_registrant_name = @domain.pending_json['new_registrant_name']
return if whitelist_blocked?(@new_registrant_email)
if @new_registrant_email.blank?
logger.info "EMAIL NOT DELIVERED: no registrant email [pending_update_expired_notification_for_new_registrant]"
return
end
mail(to: format(@new_registrant_email),
subject: "#{I18n.t(:pending_update_expired_notification_for_new_registrant_subject,
name: @domain.name)} [#{@domain.name}]")
def pending_update_expired_notification_for_new_registrant(params)
compose_from(params)
end
def pending_deleted(domain_id, old_registrant_id, should_deliver)
@ -178,8 +119,9 @@ class DomainMailer < ApplicationMailer
def expiration_reminder(domain_id)
@domain = Domain.find_by(id: domain_id)
return unless @domain
return if @domain.nil? || !@domain.statuses.include?(DomainStatus::EXPIRED) || whitelist_blocked?(@domain.registrant.email)
return if whitelist_blocked?(@domain.registrant.email)
mail(to: format(@domain.registrant.email),
subject: "#{I18n.t(:expiration_remind_subject,
name: @domain.name)} [#{@domain.name}]")
@ -197,4 +139,18 @@ class DomainMailer < ApplicationMailer
subject: "#{I18n.t(:force_delete_subject)}"
)
end
private
# app/models/DomainMailModel provides the data for mail that can be composed_from
# which ensures that values of objects are captured when they are valid, not later when this method is executed
def compose_from(params)
@params = params
return if delivery_off?(params, params[:deliver_emails])
return if whitelist_blocked?(params[:recipient])
params[:errors].map do |error|
logger.warn error
return
end
mail(to: params[:recipient], subject: params[:subject])
end
end

View file

@ -118,9 +118,11 @@ class Ability
end
def static_registrant
customer_service
can :manage, :registrant_domains
can :manage, :registrant_whois
can :manage, Depp::Domain
can :manage, Domain
end
def user

View file

@ -6,6 +6,7 @@ class AccountActivity < ActiveRecord::Base
belongs_to :bank_transaction
belongs_to :invoice
CREATE = 'create'
RENEW = 'renew'
ADD_CREDIT = 'add_credit'
@ -25,10 +26,12 @@ class AccountActivity < ActiveRecord::Base
attributes = %w(description activity_type created_at sum)
CSV.generate(headers: true) do |csv|
csv << %w(description activity_type receipt_date sum)
csv << %w(registrar description activity_type receipt_date sum)
all.each do |x| # rubocop:disable Rails/FindEach
csv << attributes.map { |attr| x.send(attr) }
attrs = [x.account.registrar.try(:code)]
attrs += attributes.map { |attr| x.send(attr) }
csv << attrs
end
end
end

View file

@ -32,7 +32,7 @@ class BankLink
hash["VK_AMOUNT"] = number_with_precision(invoice.sum_cache, :precision => 2, :separator => ".")
hash["VK_CURR"] = invoice.currency
hash["VK_REF"] = ""
hash["VK_MSG"] = "Order nr. #{invoice.number}"
hash["VK_MSG"] = invoice.description
hash["VK_RETURN"] = controller.registrar_return_payment_with_url(type)
hash["VK_CANCEL"] = controller.registrar_return_payment_with_url(type)
hash["VK_DATETIME"] = Time.now.strftime("%Y-%m-%dT%H:%M:%S%z")
@ -101,6 +101,7 @@ class BankLink
transaction.buyer_iban = params["VK_SND_ACC"]
transaction.buyer_name = params["VK_SND_NAME"]
transaction.paid_at = Time.parse(params["VK_T_DATETIME"])
transaction.save!
transaction.autobind_invoice
end

View file

@ -16,21 +16,32 @@ class BankTransaction < ActiveRecord::Base
account_activity.invoice
end
def invoice_num
return @invoice_no if defined?(@invoice_no)
match = description.match(/^[^\d]*(\d+)/)
return unless match
@invoice_no = match[1].try(:to_i)
end
def invoice
@invoice ||= registrar.invoices.find_by(number: invoice_num) if registrar
end
def registrar
@registrar ||= Registrar.find_by(reference_no: reference_no)
end
# For successful binding, reference number, invoice id and sum must match with the invoice
# rubocop: disable Metrics/PerceivedComplexity
# rubocop: disable Metrics/CyclomaticComplexity
def autobind_invoice
return if binded?
registrar = Registrar.find_by(reference_no: reference_no)
return unless registrar
match = description.match(/^[^\d]*(\d+)/)
return unless match
invoice_no = match[1].to_i
return unless invoice_no
invoice = registrar.invoices.find_by(number: invoice_no)
return unless invoice_num
return unless invoice
return if invoice.binded?

View file

@ -1,5 +1,50 @@
class BlockedDomain < ActiveRecord::Base
include Versions
before_save :generate_data
after_destroy :remove_data
after_initialize -> { self.names = [] if names.nil? }
validates :name, domain_name: true, uniqueness: true
class << self
def by_domain name
where(name: name)
end
def any_of_domains names
where(name: names)
end
end
def name= val
super SimpleIDN.to_unicode(val)
end
def generate_data
return if Domain.where(name: name).any?
wr = Whois::Record.find_or_initialize_by(name: name)
wr.json = @json = generate_json # we need @json to bind to class
wr.body = generate_body
wr.save
end
alias_method :update_whois_record, :generate_data
def generate_body
template = Rails.root.join("app/views/for_models/whois_other.erb".freeze)
ERB.new(template.read, nil, "-").result(binding)
end
def generate_json
h = HashWithIndifferentAccess.new
h[:name] = self.name
h[:status] = ['Blocked']
h
end
def remove_data
UpdateWhoisRecordJob.enqueue name, 'blocked'
end
end

View file

@ -0,0 +1,83 @@
=begin
The portal for registrants has to offer an overview of the domains the user is related to directly or through an organisation.
Personal relation is defined by matching the personal identification code associated with a domain and the one acquired on
authentication using electronic ID. Association through a business organisation requires a query to business registry.
* when user logs in the personal identification code is sent to business registry (using XML service)
* business registry returns the list of business registry codes the user is a board member of
* the list is cached for two days (configurable)
* during that time no new queries are made to business registry for that personal identification code
and the cached organisation code listing is used
* user sees the listing of domains that are associated with him/her directly or through registered organisation
* UI of the portal displays the list of organisation codes and names used to fetch additional domains for the user
(currently by clicking on a username in top right corner of the screen).
Also time and date of the query to the business registry is displayed with the list of organisations.
* if the query to the business registry fails for any reason the list of
domains associated directly with the user is still displayed with an error message indicating a problem
with receiving current list business entities. Outdated list of organisations cannot be used.
=end
class BusinessRegistryCache < ActiveRecord::Base
# 1. load domains by business
# 2. load domains by person
def associated_contacts
contact_ids = Contact.where(ident_type: 'org', ident: associated_businesses, ident_country_code: 'EE').pluck(:id)
contact_ids += Contact.where(ident_type: 'priv', ident: ident, ident_country_code: ident_country_code).pluck(:id)
contact_ids
end
def associated_domain_ids
domain_ids = []
contact_ids = associated_contacts
unless contact_ids.blank?
domain_ids = DomainContact.distinct.where(contact_id: contact_ids).pluck(:domain_id)
end
domain_ids
end
def associated_domains
Domain.includes(:registrar, :registrant).where(id: associated_domain_ids)
end
class << self
def fetch_associated_domains(ident_code, ident_cc)
fetch_by_ident_and_cc(ident_code, ident_cc).associated_domains
end
def fetch_by_ident_and_cc(ident_code, ident_cc)
cache = BusinessRegistryCache.where(ident: ident_code, ident_country_code: ident_cc).first_or_initialize
msg_start = "[Ariregister] #{ident_cc}-#{ident_code}:"
# fetch new data if cache is expired
if cache.retrieved_on && cache.retrieved_on > (Time.zone.now - Setting.days_to_keep_business_registry_cache.days)
Rails.logger.info("#{msg_start} Info loaded from cache")
return cache
end
cache.attributes = business_registry.associated_businesses(ident_code, ident_cc)
Rails.logger.info("#{msg_start} Info loaded from server")
cache.save
cache
end
def business_registry
Soap::Arireg.new
end
def purge
STDOUT << "#{Time.zone.now.utc} - Starting Purge of old BusinessRegistry data from cache\n" unless Rails.env.test?
purged = 0
BusinessRegistryCache.where('retrieved_on < ?',
Time.zone.now < Setting.days_to_keep_business_registry_cache.days).each do |br|
br.destroy and purged += 1
end
STDOUT << "#{Time.zone.now.utc} - Finished purging #{purged} old BusinessRegistry cache items\n" unless Rails.env.test?
end
end
end

View file

@ -1,23 +1,30 @@
module UserEvents
extend ActiveSupport::Concern
# TODO: remove old
# module ClassMethods
# def registrar_events(id)
# registrar = Registrar.find(id)
# return [] unless registrar
# @events = []
# registrar.users.each { |user| @events << user_events(user.id) }
# registrar.epp_users.each { |user| @events << epp_user_events(user.id) }
# @events
# end
# def user_events(id)
# where(whodunnit: id.to_s)
# end
# def epp_user_events(id)
# where(whodunnit: "#{id}-EppUser")
# end
# end
included do
# EPP requires a server defined creator ID, which should be registrar code if we have one
def cr_id
# try this, rebuild user for registrar before searching history? really?
registrar = self.creator.try(:registrar)
if registrar.present? # Did creator return a kind of User that has a registrar?
registrar.code
else
if self.versions.first.try(:object).nil?
changes = self.versions.first.try(:object_changes)
cr_registrar_id = changes['registrar_id'].second if changes.present?
else
# untested, expected never to execute
cr_registrar_id = self.versions.first.object['registrar_id']
end
if cr_registrar_id.present?
Registrar.find(cr_registrar_id).code
else
# cr_id optional for domain, but required for contact; but we want something here anyway
self.creator_str # Fallback if we failed, maybe we can find a string here
end
end
end
end
end

View file

@ -3,6 +3,7 @@ module Versions
extend ActiveSupport::Concern
included do
attr_accessor :version_loader
has_paper_trail class_name: "#{model_name}Version"
# add creator and updator
@ -22,30 +23,28 @@ module Versions
def creator
return nil if creator_str.blank?
if creator_str =~ /^\d+-AdminUser:/
creator = AdminUser.find_by(id: creator_str)
elsif creator_str =~ /^\d+-ApiUser:/
creator = ApiUser.find_by(id: creator_str)
elsif creator_str =~ /^\d+-api-/ # depricated
creator = ApiUser.find_by(id: creator_str)
end
creator = user_from_id_role_username creator_str
creator.present? ? creator : creator_str
end
def updator
return nil if updator_str.blank?
if updator_str =~ /^\d+-AdminUser:/
updator = AdminUser.find_by(id: updator_str)
elsif updator_str =~ /^\d+-ApiUser:/
updator = ApiUser.find_by(id: updator_str)
elsif updator_str =~ /^\d+-api-/ # depricated
updator = ApiUser.find_by(id: updator_str)
updator = user_from_id_role_username updator_str
updator.present? ? updator : updator_str
end
updator.present? ? updator : updator_str
def user_from_id_role_username(str)
user = ApiUser.find_by(id: $1) if str =~ /^(\d+)-(ApiUser:|api-)/
unless user.present?
user = AdminUser.find_by(id: $1) if str =~ /^(\d+)-AdminUser:/
unless user.present?
# on import we copied Registrar name, which may eql code
registrar = Registrar.find_by(name: str)
# assume each registrar has only one user
user = registrar.api_users.first if registrar
end
end
user
end
# callbacks
@ -57,4 +56,23 @@ module Versions
domains.each(&:touch_with_version)
end
end
module ClassMethods
def all_versions_for(ids, time)
ver_klass = paper_trail_version_class
from_history = ver_klass.where(item_id: ids.to_a).
order(:item_id).
preceding(time + 1, true).
select("distinct on (item_id) #{ver_klass.table_name}.*").
map do |ver|
o = new(ver.object)
o.version_loader = ver
ver.object_changes.to_h.each { |k, v| o[k]=v[-1] }
o
end
not_in_history = where(id: (ids.to_a - from_history.map(&:id)))
from_history + not_in_history
end
end
end

View file

@ -1,6 +1,7 @@
class Contact < ActiveRecord::Base
include Versions # version/contact_version.rb
include EppErrors
include UserEvents
belongs_to :registrar
has_many :domain_contacts
@ -11,6 +12,10 @@ class Contact < ActiveRecord::Base
# TODO: remove later
has_many :depricated_statuses, class_name: 'DepricatedContactStatus', dependent: :destroy
has_paper_trail class_name: "ContactVersion", meta: { children: :children_log }
attr_accessor :legal_document_id
accepts_nested_attributes_for :legal_documents
validates :name, :phone, :email, :ident, :ident_type,
@ -28,9 +33,12 @@ class Contact < ActiveRecord::Base
uniqueness: { message: :epp_id_taken },
format: { with: /\A[\w\-\:\.\_]*\z/i, message: :invalid },
length: { maximum: 100, message: :too_long_contact_code }
validate :ident_valid_format?
validate :val_ident_type
validate :val_ident_valid_format?
validate :uniq_statuses?
validate :validate_html
validate :val_country_code
after_initialize do
self.statuses = [] if statuses.nil?
@ -38,8 +46,9 @@ class Contact < ActiveRecord::Base
self.ident_updated_at = Time.zone.now if new_record? && ident_updated_at.blank?
end
before_validation :set_ident_country_code
before_validation :to_upcase_country_code
before_validation :prefix_code
before_validation :strip_email
before_create :generate_auth_info
before_update :manage_emails
@ -48,7 +57,7 @@ class Contact < ActiveRecord::Base
return nil unless deliver_emails == true
emails = []
emails << [email, email_was]
emails << domains.map(&:registrant_email) if domains.present?
# emails << domains.map(&:registrant_email) if domains.present?
emails = emails.flatten.uniq
emails.each do |e|
ContactMailer.email_updated(email_was, e, id, deliver_emails).deliver
@ -57,6 +66,11 @@ class Contact < ActiveRecord::Base
before_save :manage_statuses
def manage_statuses
if domain_transfer # very ugly but need better workflow
self.statuses = statuses | [OK, LINKED]
return
end
manage_linked
manage_ok
end
@ -70,7 +84,7 @@ class Contact < ActiveRecord::Base
ORG = 'org'
PRIV = 'priv'
BIRTHDAY = 'birthday'
BIRTHDAY = 'birthday'.freeze
PASSPORT = 'passport'
IDENT_TYPES = [
@ -80,6 +94,7 @@ class Contact < ActiveRecord::Base
]
attr_accessor :deliver_emails
attr_accessor :domain_transfer # hack but solves problem faster
#
# STATUSES
@ -203,6 +218,21 @@ class Contact < ActiveRecord::Base
['DeleteProhibited', SERVER_DELETE_PROHIBITED]
]
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
end
end
def roid
@ -213,13 +243,24 @@ class Contact < ActiveRecord::Base
name || '[no name]'
end
def ident_valid_format?
case ident_type
when 'priv'
def val_ident_type
errors.add(:ident_type, :epp_ident_type_invalid, code: code) if !%w(org priv birthday).include?(ident_type)
end
def val_ident_valid_format?
case ident_country_code
when 'EE'
code = Isikukood.new(ident)
errors.add(:ident, :invalid_EE_identity_format) unless code.valid?
when 'EE'.freeze
err_msg = "invalid_EE_identity_format#{"_update" if id}".to_sym
case ident_type
when 'priv'.freeze
errors.add(:ident, err_msg) unless Isikukood.new(ident).valid?
when 'org'.freeze
# !%w(1 7 8 9).freeze.include?(ident.first) ||
if ident.size != 8 || !(ident =~/\A[0-9]{8}\z/)
errors.add(:ident, err_msg)
end
when BIRTHDAY
errors.add(:ident, err_msg) if id.blank? # only for create action right now. Later for all of them
end
end
end
@ -252,6 +293,10 @@ class Contact < ActiveRecord::Base
!org?
end
def birthday?
ident_type == BIRTHDAY
end
def generate_auth_info
return if @generate_auth_info_disabled
return if auth_info.present?
@ -303,22 +348,36 @@ class Contact < ActiveRecord::Base
# TODO: refactor, it should not allow to destroy with normal destroy,
# no need separate method
# should use only in transaction
def destroy_and_clean
def destroy_and_clean frame
if domains_present?
errors.add(:domains, :exist)
return false
end
legal_document_data = Epp::Domain.parse_legal_document_from_frame(frame)
if legal_document_data
doc = LegalDocument.create(
documentable_type: Contact,
document_type: legal_document_data[:type],
body: legal_document_data[:body]
)
self.legal_documents = [doc]
self.legal_document_id = doc.id
self.save
end
destroy
end
def set_ident_country_code
return true unless ident_country_code_changed? && ident_country_code.present?
code = Country.new(ident_country_code)
if code
self.ident_country_code = code.alpha2
else
errors.add(:ident, :invalid_country_code)
def to_upcase_country_code
self.ident_country_code = ident_country_code.upcase if ident_country_code
self.country_code = country_code.upcase if country_code
end
def val_country_code
errors.add(:ident, :invalid_country_code) unless Country.new(ident_country_code)
errors.add(:ident, :invalid_country_code) unless Country.new(country_code)
end
def related_domain_descriptions
@ -365,6 +424,10 @@ class Contact < ActiveRecord::Base
"#{code} #{name}"
end
def strip_email
self.email = email.to_s.strip
end
# what we can do load firstly by registrant
# if total is smaller than needed, the load more
@ -388,7 +451,10 @@ class Contact < ActiveRecord::Base
# fetch domains
domains = Domain.where("domains.id IN (#{filter_sql})").includes(:registrar).page(page).per(per)
domains = Domain.where("domains.id IN (#{filter_sql})")
domains = domains.where("domains.id" => params[:leave_domains]) if params[:leave_domains]
domains = domains.includes(:registrar).page(page).per(per)
if sorts.first == "registrar_name".freeze
# using small rails hack to generate outer join
domains = domains.includes(:registrar).where.not(registrars: {id: nil}).order("registrars.name #{order} NULLS LAST")
@ -407,6 +473,30 @@ class Contact < ActiveRecord::Base
domains
end
def all_registrant_domains(page: nil, per: nil, params: {}, registrant: nil)
if registrant
sorts = params.fetch(:sort, {}).first || []
sort = Domain.column_names.include?(sorts.first) ? sorts.first : "valid_to"
order = {"asc"=>"desc", "desc"=>"asc"}[sorts.second] || "desc"
domain_ids = DomainContact.distinct.where(contact_id: registrant.id).pluck(:domain_id)
domains = Domain.where(id: domain_ids).includes(:registrar).page(page).per(per)
if sorts.first == "registrar_name".freeze
domains = domains.includes(:registrar).where.not(registrars: {id: nil}).order("registrars.name #{order} NULLS LAST")
else
domains = domains.order("#{sort} #{order} NULLS LAST")
end
domain_c = Hash.new([])
registrant_domains.where(id: domains.map(&:id)).each{|d| domain_c[d.id] |= ["Registrant".freeze] }
DomainContact.where(contact_id: id, domain_id: domains.map(&:id)).each{|d| domain_c[d.domain_id] |= [d.type] }
domains.each{|d| d.roles = domain_c[d.id].uniq}
domains
end
end
def set_linked
statuses << LINKED if statuses.detect { |s| s == LINKED }.blank?
end
@ -472,7 +562,14 @@ class Contact < ActiveRecord::Base
end
def update_related_whois_records
related_domain_descriptions.each{ |x, y| WhoisRecord.find_by(name: x).save}
names = related_domain_descriptions.keys
UpdateWhoisRecordJob.enqueue(names, :domain) if names.present?
end
def children_log
log = HashWithIndifferentAccess.new
log[:legal_documents]= [legal_document_id]
log
end
end

24
app/models/counter.rb Normal file
View file

@ -0,0 +1,24 @@
class Counter
def initialize value = 0
@value = value
end
attr_accessor :value
def method_missing *args, &blk
@value.send(*args, &blk)
end
def to_s
@value.to_s
end
def now
@value
end
# pre-increment ".+" when x not present
def next(x = 1)
@value += x
end
def prev(x = 1)
@value -= x
end
end

View file

@ -66,8 +66,9 @@ module Depp
def delete(domain_params)
xml = epp_xml.delete({
name: { value: domain_params[:name] }
}, Depp::Domain.construct_custom_params_hash(domain_params))
name: { value: domain_params[:name] }},
Depp::Domain.construct_custom_params_hash(domain_params),
(domain_params[:verified].present? && 'yes'))
current_user.request(xml)
end
@ -152,23 +153,17 @@ module Depp
}
end
data.css('dsData').each_with_index do |x, i|
ds = {
data.css('keyData').each_with_index do |x, i|
ret[:dnskeys_attributes][i] = {
flags: x.css('flags').text,
protocol: x.css('protocol').text,
alg: x.css('alg').text,
public_key: x.css('pubKey').text,
ds_key_tag: x.css('keyTag').first.try(:text),
ds_alg: x.css('alg').first.try(:text),
ds_digest_type: x.css('digestType').first.try(:text),
ds_digest: x.css('digest').first.try(:text)
}
kd = x.css('keyData').first
ds.merge!({
flags: kd.css('flags').first.try(:text),
protocol: kd.css('protocol').first.try(:text),
alg: kd.css('alg').first.try(:text),
public_key: kd.css('pubKey').first.try(:text)
}) if kd
ret[:dnskeys_attributes][i] = ds
end
data.css('status').each_with_index do |x, i|
@ -220,7 +215,8 @@ module Depp
rem_arr << { _anonymus: rem_anon } if rem_anon.any?
if domain_params[:registrant] != old_domain_params[:registrant]
chg = [{ registrant: { value: domain_params[:registrant] } }]
chg = [{ registrant: { value: domain_params[:registrant] } }] if !domain_params[:verified].present?
chg = [{ registrant: { value: domain_params[:registrant], attrs: { verified: 'yes' } } }] if domain_params[:verified]
end
add_arr = nil if add_arr.none?

179
app/models/directo.rb Normal file
View file

@ -0,0 +1,179 @@
class Directo < ActiveRecord::Base
DOMAIN_TO_PRODUCT = {"ee" => "01EE", "com.ee" => "02COM", "pri.ee" => "03PRI", "fie.ee"=>"04FIE", "med.ee" => "05MED"}.freeze
belongs_to :item, polymorphic: true
def self.send_receipts
new_trans = Invoice.where(invoice_type: "DEB", in_directo: false).where(cancelled_at: nil)
total = new_trans.count
counter = 0
Rails.logger.info("[DIRECTO] Will try to send #{total} invoices")
new_trans.find_in_batches(batch_size: 10).each do |group|
mappers = {} # need them as no direct connection between invoice
builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
xml.invoices {
group.each do |invoice|
if invoice.account_activity.nil? || invoice.account_activity.bank_transaction.nil? ||
invoice.account_activity.bank_transaction.sum.nil? || invoice.account_activity.bank_transaction.sum != invoice.sum_cache
Rails.logger.info("[DIRECTO] Invoice #{invoice.number} has been skipped")
next
end
counter += 1
num = invoice.number
mappers[num] = invoice
xml.invoice(
"SalesAgent" => Setting.directo_sales_agent,
"Number" => num,
"InvoiceDate" => invoice.created_at.strftime("%Y-%m-%dT%H:%M:%S"),
"PaymentTerm" => Setting.directo_receipt_payment_term,
"Currency" => invoice.currency,
"CustomerCode"=> invoice.buyer.try(:directo_handle)
){
xml.line(
"ProductID" => Setting.directo_receipt_product_name,
"Quantity" => 1,
"UnitPriceWoVAT" => ActionController::Base.helpers.number_with_precision(invoice.sum_cache/(1+invoice.vat_prc), precision: 2, separator: "."),
"ProductName" => invoice.description
)
}
end
}
end
data = builder.to_xml.gsub("\n",'')
response = RestClient::Request.execute(url: ENV['directo_invoice_url'], method: :post, payload: {put: "1", what: "invoice", xmldata: data}, verify_ssl: false).to_s
dump_result_to_db(mappers, response)
end
STDOUT << "#{Time.zone.now.utc} - Directo receipts sending finished. #{counter} of #{total} are sent\n"
end
def self.dump_result_to_db mappers, xml
Nokogiri::XML(xml).css("Result").each do |res|
obj = mappers[res.attributes["docid"].value.to_i]
obj.directo_records.create!(response: res.as_json.to_h, invoice_number: obj.number)
obj.update_columns(in_directo: true)
Rails.logger.info("[DIRECTO] Invoice #{res.attributes["docid"].value} was pushed and return is #{res.as_json.to_h.inspect}")
end
end
def self.send_monthly_invoices(debug: false)
@debug = debug
I18n.locale = :et
month = Time.now - 1.month
invoices_until = month.end_of_month
date_format = "%Y-%m-%d"
invoice_counter= Counter.new
min_directo = Setting.directo_monthly_number_min.presence.try(:to_i)
max_directo = Setting.directo_monthly_number_max.presence.try(:to_i)
last_directo = [Setting.directo_monthly_number_last.presence.try(:to_i), min_directo].compact.max || 0
if max_directo && max_directo <= last_directo
raise "Directo counter is out of period (max allowed number is smaller than last counter number)"
end
directo_next = last_directo
Registrar.where.not(test_registrar: true).find_each do |registrar|
unless registrar.cash_account
Rails.logger.info("[DIRECTO] Monthly invoice for registrar #{registrar.id} has been skipped as it doesn't has cash_account")
next
end
counter = Counter.new(1)
items = {}
registrar_activities = AccountActivity.where(account_id: registrar.account_ids).where("created_at BETWEEN ? AND ?",month.beginning_of_month, month.end_of_month)
# adding domains items
registrar_activities.where(activity_type: [AccountActivity::CREATE, AccountActivity::RENEW]).each do |activity|
pricelist = load_activity_pricelist(activity)
unless pricelist
Rails.logger.error("[DIRECTO] Skipping activity #{activity.id} as pricelist not found")
next
end
pricelist.years_amount.times do |i|
year = i+1
hash = {
"ProductID" => DOMAIN_TO_PRODUCT[pricelist.category],
"Unit" => "tk",
"ProductName" => ".#{pricelist.category} registreerimine: #{pricelist.years_amount} aasta",
"UnitPriceWoVAT" => pricelist.price_decimal/pricelist.years_amount
}
hash["StartDate"] = (activity.created_at + (year-1).year).end_of_month.strftime(date_format) if year > 1
hash["EndDate"] = (activity.created_at + (year-1).year + 1).end_of_month.strftime(date_format) if year > 1
if items.has_key?(hash)
items[hash]["Quantity"] += 1
else
items[hash] = {"RN"=>counter.next, "RR" => counter.now - i, "Quantity"=> 1}
end
end
end
#adding prepaiments
if items.any?
total = 0
items.each{ |key, val| total += val["Quantity"] * key["UnitPriceWoVAT"] }
hash = {"ProductID" => Setting.directo_receipt_product_name, "Unit" => "tk", "ProductName" => "Domeenide ettemaks", "UnitPriceWoVAT"=>total}
items[hash] = {"RN"=>counter.next, "RR" => counter.now, "Quantity"=> -1}
end
# generating XML
if items.any?
directo_next += 1
invoice_counter.next
builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
xml.invoices{
xml.invoice("Number" =>directo_next,
"InvoiceDate" =>invoices_until.strftime(date_format),
"PaymentTerm" =>Setting.directo_receipt_payment_term,
"CustomerCode"=>registrar.directo_handle,
"Language" =>"",
"Currency" =>registrar_activities.first.currency,
"SalesAgent" =>Setting.directo_sales_agent){
xml.line("RN" => 1, "RR"=>1, "ProductName"=> "Domeenide registreerimine - #{I18n.l(invoices_until, format: "%B %Y").titleize}")
items.each do |line, val|
xml.line(val.merge(line))
end
}
}
end
data = builder.to_xml.gsub("\n",'')
response = RestClient::Request.execute(url: ENV['directo_invoice_url'], method: :post, payload: {put: "1", what: "invoice", xmldata: data}, verify_ssl: false).to_s
if @debug
STDOUT << "#{Time.zone.now.utc} - Directo xml had to be sent #{data}\n"
else
Setting.directo_monthly_number_last = directo_next
Nokogiri::XML(response).css("Result").each do |res|
Directo.create!(request: data, response: res.as_json.to_h, invoice_number: directo_next)
Rails.logger.info("[DIRECTO] Invoice #{res.attributes["docid"].value} was pushed and return is #{res.as_json.to_h.inspect}")
end
end
else
Rails.logger.info("[DIRECTO] Registrar #{registrar.id} has nothing to be sent to Directo")
end
end
STDOUT << "#{Time.zone.now.utc} - Directo invoices sending finished. #{invoice_counter.now} are sent\n"
end
def self.load_activity_pricelist activity
@pricelists ||= {}
return @pricelists[activity.log_pricelist_id] if @pricelists.has_key?(activity.log_pricelist_id)
pricelist = Pricelist.find_by(id: activity.log_pricelist_id) || PricelistVersion.find_by(item_id: activity.log_pricelist_id).try(:reify)
unless pricelist
@pricelists[activity.log_pricelist_id] = nil
Rails.logger.info("[DIRECTO] AccountActivity #{activity.id} cannot be sent as pricelist wasn't found #{activity.log_pricelist_id}")
return
end
@pricelists[activity.log_pricelist_id] = pricelist.version_at(activity.created_at) || pricelist
end
end

View file

@ -1,11 +1,14 @@
# rubocop: disable Metrics/ClassLength
class Domain < ActiveRecord::Base
include UserEvents
include Versions # version/domain_version.rb
include Statuses
has_paper_trail class_name: "DomainVersion", meta: { children: :children_log }
attr_accessor :roles
attr_accessor :legal_document_id
# TODO: whois requests ip whitelist for full info for own domains and partial info for other domains
# TODO: most inputs should be trimmed before validatation, probably some global logic?
@ -42,7 +45,7 @@ class Domain < ActiveRecord::Base
has_many :dnskeys, dependent: :destroy
has_many :keyrelays
has_one :whois_record, dependent: :destroy
has_one :whois_record # destroyment will be done in after_commit
accepts_nested_attributes_for :dnskeys, allow_destroy: true
@ -86,14 +89,11 @@ class Domain < ActiveRecord::Base
true
end
after_save :update_whois_record
after_commit :update_whois_record
after_create :update_reserved_domains
def update_reserved_domains
return unless in_reserved_list?
rd = ReservedDomain.by_domain(name).first
rd.names[name] = SecureRandom.hex
rd.save
ReservedDomain.new_password_for(name) if in_reserved_list?
end
validates :name_dirty, domain_name: true, uniqueness: true
@ -202,6 +202,31 @@ class Domain < ActiveRecord::Base
statuses.include? DomainStatus::SERVER_TECH_CHANGE_PROHIBITED
end
def self.clean_expired_pendings
ActiveSupport::Deprecation.instance.deprecation_warning(DomainCron, __method__)
DomainCron.send(__method__)
end
def self.start_expire_period
ActiveSupport::Deprecation.instance.deprecation_warning(DomainCron, __method__)
DomainCron.send(__method__)
end
def self.start_redemption_grace_period
ActiveSupport::Deprecation.instance.deprecation_warning(DomainCron, __method__)
DomainCron.send(__method__)
end
def self.start_delete_period
ActiveSupport::Deprecation.instance.deprecation_warning(DomainCron, __method__)
DomainCron.send(__method__)
end
def self.destroy_delete_candidates
ActiveSupport::Deprecation.instance.deprecation_warning(DomainCron, __method__)
DomainCron.send(__method__)
end
class << self
def convert_period_to_time(period, unit)
return (period.to_i / 365).years if unit == 'd'
@ -219,122 +244,6 @@ class Domain < ActiveRecord::Base
{ admin_contacts: :registrar }
)
end
# rubocop: disable Metrics/AbcSize
# rubocop: disable Metrics/CyclomaticComplexity
# rubocop: disable Metrics/PerceivedComplexity
def clean_expired_pendings
STDOUT << "#{Time.zone.now.utc} - Clean expired domain pendings\n" unless Rails.env.test?
expire_at = Setting.expire_pending_confirmation.hours.ago
count = 0
expired_pending_domains = Domain.where('registrant_verification_asked_at <= ?', expire_at)
expired_pending_domains.each do |domain|
unless domain.pending_update? || domain.pending_delete? || domain.pending_delete_confirmation?
msg = "#{Time.zone.now.utc} - ISSUE: DOMAIN #{domain.id}: #{domain.name} IS IN EXPIRED PENDING LIST, " \
"but no pendingDelete/pendingUpdate state present!\n"
STDOUT << msg unless Rails.env.test?
next
end
count += 1
if domain.pending_update?
DomainMailer.pending_update_expired_notification_for_new_registrant(domain.id).deliver
end
if domain.pending_delete? || domain.pending_delete_confirmation?
DomainMailer.pending_delete_expired_notification(domain.id, deliver_emails).deliver
end
domain.clean_pendings!
unless Rails.env.test?
STDOUT << "#{Time.zone.now.utc} Domain.clean_expired_pendings: ##{domain.id} (#{domain.name})\n"
end
end
STDOUT << "#{Time.zone.now.utc} - Successfully cancelled #{count} domain pendings\n" unless Rails.env.test?
count
end
# rubocop: enable Metrics/PerceivedComplexity
# rubocop: enable Metrics/AbcSize
# rubocop: enable Metrics/CyclomaticComplexity
# rubocop: disable Metrics/LineLength
def start_expire_period
STDOUT << "#{Time.zone.now.utc} - Expiring domains\n" unless Rails.env.test?
domains = Domain.where('valid_to <= ?', Time.zone.now)
domains.each do |domain|
next unless domain.expirable?
domain.set_graceful_expired
DomainMailer.expiration_reminder(domain.id).deliver
STDOUT << "#{Time.zone.now.utc} Domain.start_expire_period: ##{domain.id} (#{domain.name}) #{domain.changes}\n" unless Rails.env.test?
domain.save
end
STDOUT << "#{Time.zone.now.utc} - Successfully expired #{domains.count} domains\n" unless Rails.env.test?
end
def start_redemption_grace_period
STDOUT << "#{Time.zone.now.utc} - Setting server_hold to domains\n" unless Rails.env.test?
d = Domain.where('outzone_at <= ?', Time.zone.now)
d.each do |domain|
next unless domain.server_holdable?
domain.statuses << DomainStatus::SERVER_HOLD
STDOUT << "#{Time.zone.now.utc} Domain.start_redemption_grace_period: ##{domain.id} (#{domain.name}) #{domain.changes}\n" unless Rails.env.test?
domain.save
end
STDOUT << "#{Time.zone.now.utc} - Successfully set server_hold to #{d.count} domains\n" unless Rails.env.test?
end
def start_delete_period
STDOUT << "#{Time.zone.now.utc} - Setting delete_candidate to domains\n" unless Rails.env.test?
d = Domain.where('delete_at <= ?', Time.zone.now)
d.each do |domain|
next unless domain.delete_candidateable?
domain.statuses << DomainStatus::DELETE_CANDIDATE
STDOUT << "#{Time.zone.now.utc} Domain.start_delete_period: ##{domain.id} (#{domain.name}) #{domain.changes}\n" unless Rails.env.test?
domain.save
end
return if Rails.env.test?
STDOUT << "#{Time.zone.now.utc} - Successfully set delete_candidate to #{d.count} domains\n"
end
# rubocop:disable Rails/FindEach
# rubocop:disable Metrics/AbcSize
def destroy_delete_candidates
STDOUT << "#{Time.zone.now.utc} - Destroying domains\n" unless Rails.env.test?
c = 0
Domain.where("statuses @> '{deleteCandidate}'::varchar[]").each do |x|
Whois::Record.where('domain_id = ?', x.id).try(':destroy')
destroy_with_message x
STDOUT << "#{Time.zone.now.utc} Domain.destroy_delete_candidates: by deleteCandidate ##{x.id} (#{x.name})\n" unless Rails.env.test?
c += 1
end
Domain.where('force_delete_at <= ?', Time.zone.now).each do |x|
Whois::Record.where('domain_id = ?', x.id).try(':destroy')
destroy_with_message x
STDOUT << "#{Time.zone.now.utc} Domain.destroy_delete_candidates: by force delete time ##{x.id} (#{x.name})\n" unless Rails.env.test?
c += 1
end
STDOUT << "#{Time.zone.now.utc} - Successfully destroyed #{c} domains\n" unless Rails.env.test?
end
# rubocop: enable Metrics/AbcSize
# rubocop:enable Rails/FindEach
# rubocop: enable Metrics/LineLength
def destroy_with_message(domain)
domain.destroy
bye_bye = domain.versions.last
domain.registrar.messages.create!(
body: "#{I18n.t(:domain_deleted)}: #{domain.name}",
attached_obj_id: bye_bye.id,
attached_obj_type: bye_bye.class.to_s # DomainVersion
)
end
end
def name=(value)
@ -369,7 +278,7 @@ class Domain < ActiveRecord::Base
end
def in_reserved_list?
ReservedDomain.pw_for(name).present?
@in_reserved_list ||= ReservedDomain.by_domain(name).any?
end
def pending_transfer
@ -407,8 +316,7 @@ class Domain < ActiveRecord::Base
end
end
return false if statuses.include_any?(DomainStatus::DELETE_CANDIDATE, DomainStatus::SERVER_RENEW_PROHIBITED,
DomainStatus::CLIENT_RENEW_PROHIBITED, DomainStatus::PENDING_RENEW,
return false if statuses.include_any?(DomainStatus::DELETE_CANDIDATE, DomainStatus::PENDING_RENEW,
DomainStatus::PENDING_TRANSFER, DomainStatus::PENDING_DELETE,
DomainStatus::PENDING_UPDATE, DomainStatus::PENDING_DELETE_CONFIRMATION)
true
@ -438,8 +346,37 @@ class Domain < ActiveRecord::Base
save
end
# state changes may be done low-level - no validation
# in this metod we still save PaperTrail log.
def clean_pendings_lowlevel
statuses.delete(DomainStatus::PENDING_DELETE_CONFIRMATION)
statuses.delete(DomainStatus::PENDING_UPDATE)
statuses.delete(DomainStatus::PENDING_DELETE)
status_notes[DomainStatus::PENDING_UPDATE] = ''
status_notes[DomainStatus::PENDING_DELETE] = ''
hash = {
registrant_verification_token: nil,
registrant_verification_asked_at: nil,
pending_json: {},
status_notes: status_notes,
statuses: statuses.presence || [DomainStatus::OK],
# need this column in order to update PaperTrail version properly
updated_at: Time.now.utc
}
# PaperTrail
self.attributes = hash
record_update
clear_version_instance!
reset_transaction_id
update_columns(hash)
end
def pending_update!
old_registrant_id = registrant_id
return true if pending_update?
self.epp_pending_update = true # for epp
@ -451,8 +388,8 @@ class Domain < ActiveRecord::Base
new_registrant_email = registrant.email
new_registrant_name = registrant.name
DomainMailer.pending_update_request_for_old_registrant(id, old_registrant_id, deliver_emails).deliver
DomainMailer.pending_update_notification_for_new_registrant(id, old_registrant_id, deliver_emails).deliver
send_mail :pending_update_request_for_old_registrant
send_mail :pending_update_notification_for_new_registrant
reload # revert back to original
@ -460,6 +397,7 @@ class Domain < ActiveRecord::Base
self.registrant_verification_token = token
self.registrant_verification_asked_at = asked_at
set_pending_update
touch_always_version
pending_json['new_registrant_id'] = new_registrant_id
pending_json['new_registrant_email'] = new_registrant_email
pending_json['new_registrant_name'] = new_registrant_name
@ -525,26 +463,21 @@ class Domain < ActiveRecord::Base
period_i ||= period
unit ||= period_unit
# TODO: test if name.scan(/\.(.+)\z/).first.first is faster
zone = name.split('.').drop(1).join('.')
p = period_i / 365 if unit == 'd'
p = period_i / 12 if unit == 'm'
p = period_i if unit == 'y'
if p > 1
p = "#{p}years"
else
p = "#{p}year"
end
Pricelist.pricelist_for(zone, operation, p)
Pricelist.pricelist_for(zone, operation, "#{p}year".pluralize(p))
end
### VALIDATIONS ###
def validate_nameserver_ips
nameservers.each do |ns|
next unless ns.hostname.end_with?(name)
nameservers.to_a.reject(&:marked_for_destruction?).each do |ns|
next unless ns.hostname.end_with?(".#{name}")
next if ns.ipv4.present?
errors.add(:nameservers, :invalid) if errors[:nameservers].blank?
ns.errors.add(:ipv4, :blank)
@ -574,7 +507,7 @@ class Domain < ActiveRecord::Base
def name_in_wire_format
res = ''
parts = name.split('.')
parts = name_puny.split('.')
parts.each do |x|
res += format('%02X', x.length) # length of label in hex
res += x.each_byte.map { |b| format('%02X', b) }.join # label
@ -642,7 +575,7 @@ class Domain < ActiveRecord::Base
statuses << DomainStatus::SERVER_MANUAL_INZONE
end
self.force_delete_at = Time.zone.now + Setting.redemption_grace_period.days unless force_delete_at
self.force_delete_at = (Time.zone.now + (Setting.redemption_grace_period.days + 1.day)).utc.beginning_of_day unless force_delete_at
transaction do
save!(validate: false)
registrar.messages.create!(
@ -671,7 +604,7 @@ class Domain < ActiveRecord::Base
def set_graceful_expired
self.outzone_at = valid_to + Setting.expire_warning_period.days
self.delete_at = outzone_at + Setting.redemption_grace_period.days
self.delete_at = (outzone_at + (Setting.redemption_grace_period.days + 1.day)).utc.beginning_of_day
self.statuses |= [DomainStatus::EXPIRED]
end
@ -679,7 +612,7 @@ class Domain < ActiveRecord::Base
# TODO: currently valid_to attribute update logic is open
# self.valid_to = valid_from + self.class.convert_period_to_time(period, period_unit)
self.outzone_at = Time.zone.now + Setting.expire_warning_period.days
self.delete_at = Time.zone.now + Setting.redemption_grace_period.days
self.delete_at = (Time.zone.now + (Setting.redemption_grace_period.days + 1.day)).utc.beginning_of_day
statuses << DomainStatus::EXPIRED
end
@ -710,8 +643,12 @@ class Domain < ActiveRecord::Base
case s
when DomainStatus::PENDING_DELETE
self.delete_at = nil
# Handle any other special remove cases?
# when DomainStatus::FORCE_DELETE unset_force_delete
when DomainStatus::SERVER_MANUAL_INZONE # removal causes server hold to set
self.outzone_at = Time.zone.now if self.force_delete_at.present?
when DomainStatus::DomainStatus::EXPIRED # removal causes server hold to set
self.outzone_at = self.valid_to + 15.day
when DomainStatus::DomainStatus::SERVER_HOLD # removal causes server hold to set
self.outzone_at = nil
end
end
end
@ -802,13 +739,15 @@ class Domain < ActiveRecord::Base
log[:admin_contacts] = admin_contact_ids
log[:tech_contacts] = tech_contact_ids
log[:nameservers] = nameserver_ids
log[:registrant] = [registrant_id]
log[:dnskeys] = dnskey_ids
log[:domain_statuses]= domain_status_ids
log[:legal_documents]= [legal_document_id]
log[:registrant] = [registrant_id]
log
end
def update_whois_record
whois_record.blank? ? create_whois_record : whois_record.save
UpdateWhoisRecordJob.enqueue name, 'domain'
end
def status_notes_array=(notes)
@ -818,5 +757,24 @@ class Domain < ActiveRecord::Base
status_notes[status] = notes[i]
end
end
def send_mail(action)
DomainMailer.send(action, DomainMailModel.new(self).send(action)).deliver
end
def self.to_csv
CSV.generate do |csv|
csv << column_names
all.each do |domain|
csv << domain.attributes.values_at(*column_names)
end
end
end
def self.pdf(html)
kit = PDFKit.new(html)
kit.to_pdf
end
end
# rubocop: enable Metrics/ClassLength

132
app/models/domain_cron.rb Normal file
View file

@ -0,0 +1,132 @@
class DomainCron
def self.clean_expired_pendings
STDOUT << "#{Time.zone.now.utc} - Clean expired domain pendings\n" unless Rails.env.test?
expire_at = Setting.expire_pending_confirmation.hours.ago
count = 0
expired_pending_domains = Domain.where('registrant_verification_asked_at <= ?', expire_at)
expired_pending_domains.each do |domain|
unless domain.pending_update? || domain.pending_delete? || domain.pending_delete_confirmation?
msg = "#{Time.zone.now.utc} - ISSUE: DOMAIN #{domain.id}: #{domain.name} IS IN EXPIRED PENDING LIST, " \
"but no pendingDelete/pendingUpdate state present!\n"
STDOUT << msg unless Rails.env.test?
next
end
count += 1
if domain.pending_update?
DomainMailer.pending_update_expired_notification_for_new_registrant(domain.id).deliver
end
if domain.pending_delete? || domain.pending_delete_confirmation?
DomainMailer.pending_delete_expired_notification(domain.id, true).deliver
end
domain.clean_pendings_lowlevel
unless Rails.env.test?
STDOUT << "#{Time.zone.now.utc} DomainCron.clean_expired_pendings: ##{domain.id} (#{domain.name})\n"
end
UpdateWhoisRecordJob.enqueue domain.name, 'domain'
end
STDOUT << "#{Time.zone.now.utc} - Successfully cancelled #{count} domain pendings\n" unless Rails.env.test?
count
end
def self.start_expire_period
STDOUT << "#{Time.zone.now.utc} - Expiring domains\n" unless Rails.env.test?
domains = Domain.where('valid_to <= ?', Time.zone.now)
marked = 0
real = 0
domains.each do |domain|
next unless domain.expirable?
real += 1
domain.set_graceful_expired
STDOUT << "#{Time.zone.now.utc} DomainCron.start_expire_period: ##{domain.id} (#{domain.name}) #{domain.changes}\n" unless Rails.env.test?
domain.save(validate: false) and marked += 1
end
STDOUT << "#{Time.zone.now.utc} - Successfully expired #{marked} of #{real} domains\n" unless Rails.env.test?
end
def self.start_redemption_grace_period
STDOUT << "#{Time.zone.now.utc} - Setting server_hold to domains\n" unless Rails.env.test?
d = Domain.where('outzone_at <= ?', Time.zone.now)
marked = 0
real = 0
d.each do |domain|
next unless domain.server_holdable?
real += 1
domain.statuses << DomainStatus::SERVER_HOLD
STDOUT << "#{Time.zone.now.utc} DomainCron.start_redemption_grace_period: ##{domain.id} (#{domain.name}) #{domain.changes}\n" unless Rails.env.test?
domain.save(validate: false) and marked += 1
end
STDOUT << "#{Time.zone.now.utc} - Successfully set server_hold to #{marked} of #{real} domains\n" unless Rails.env.test?
marked
end
#doing nothing, deprecated
def self.start_delete_period
# begin
# STDOUT << "#{Time.zone.now.utc} - Setting delete_candidate to domains\n" unless Rails.env.test?
#
# d = Domain.where('delete_at <= ?', Time.zone.now)
# marked = 0
# real = 0
# d.each do |domain|
# next unless domain.delete_candidateable?
# real += 1
# domain.statuses << DomainStatus::DELETE_CANDIDATE
# STDOUT << "#{Time.zone.now.utc} DomainCron.start_delete_period: ##{domain.id} (#{domain.name})\n" unless Rails.env.test?
# ::PaperTrail.whodunnit = "cron - #{__method__}"
# domain.save(validate: false) and marked += 1
# end
# ensure # the operator should see what was accomplished
# STDOUT << "#{Time.zone.now.utc} - Finished setting delete_candidate - #{marked} out of #{real} successfully set\n" unless Rails.env.test?
# end
# marked
end
def self.destroy_delete_candidates
STDOUT << "#{Time.zone.now.utc} - Destroying domains\n" unless Rails.env.test?
c = 0
Domain.where('delete_at <= ?', Time.zone.now).each do |x|
next unless x.delete_candidateable?
x.statuses << DomainStatus::DELETE_CANDIDATE
# If domain successfully saved, add it to delete schedule
if x.save(validate: false)
::PaperTrail.whodunnit = "cron - #{__method__}"
DomainDeleteJob.enqueue(x.id, run_at: rand(((24*60) - (DateTime.now.hour * 60 + DateTime.now.minute))).minutes.from_now)
STDOUT << "#{Time.zone.now.utc} Domain.destroy_delete_candidates: job added by deleteCandidate status ##{x.id} (#{x.name})\n" unless Rails.env.test?
c += 1
end
end
Domain.where('force_delete_at <= ?', Time.zone.now).each do |x|
DomainDeleteJob.enqueue(x.id, run_at: rand(((24*60) - (DateTime.now.hour * 60 + DateTime.now.minute))).minutes.from_now)
STDOUT << "#{Time.zone.now.utc} DomainCron.destroy_delete_candidates: job added by force delete time ##{x.id} (#{x.name})\n" unless Rails.env.test?
c += 1
end
STDOUT << "#{Time.zone.now.utc} - Job destroy added for #{c} domains\n" unless Rails.env.test?
end
# rubocop: enable Metrics/AbcSize
# rubocop:enable Rails/FindEach
# rubocop: enable Metrics/LineLength
def self.destroy_with_message(domain)
domain.destroy
bye_bye = domain.versions.last
domain.registrar.messages.create!(
body: "#{I18n.t(:domain_deleted)}: #{domain.name}",
attached_obj_id: bye_bye.id,
attached_obj_type: bye_bye.class.to_s # DomainVersion
)
end
end

View file

@ -0,0 +1,159 @@
class DomainMailModel
# Capture current values used in app/views/mailers/domain_mailer/* and app/mailers/domain_mailer will send later
def initialize(domain)
@domain = domain
@params = {errors: [], deliver_emails: domain.deliver_emails, id: domain.id}
end
def pending_update_request_for_old_registrant
registrant_old
subject(:pending_update_request_for_old_registrant_subject)
confirm_update
domain_info
compose
end
def pending_update_notification_for_new_registrant
registrant # new registrant at this point
subject(:pending_update_notification_for_new_registrant_subject)
domain_info
compose
end
def pending_update_rejected_notification_for_new_registrant
registrant_pending
subject(:pending_update_rejected_notification_for_new_registrant_subject)
@params[:deliver_emails] = true # triggered from que
@params[:registrar_name] = @domain.registrar.name
compose
end
def pending_update_expired_notification_for_new_registrant
registrant_pending
subject(:pending_update_expired_notification_for_new_registrant_subject)
domain_info
compose
end
def pending_deleted
registrant
subject(:domain_pending_deleted_subject)
confirm_delete
compose
end
def pending_delete_rejected_notification
registrant
subject(:pending_delete_rejected_notification_subject)
compose
end
def pending_delete_expired_notification
registrant
subject(:pending_delete_expired_notification_subject)
compose
end
def delete_confirmation
registrant
subject(:delete_confirmation_subject)
compose
end
def force_delete
admins
subject(:force_delete_subject)
compose
end
private
def registrant_old
@params[:recipient] = format Registrant.find(@domain.registrant_id_was).email
end
def registrant
@params[:recipient] = format @domain.registrant.email
end
def registrant_pending
@params[:recipient] = format @domain.pending_json['new_registrant_email']
@params[:new_registrant_name] = @domain.pending_json['new_registrant_name']
@params[:old_registrant_name] = @domain.registrant.name
end
# registrant and domain admin contacts
def admins
emails = ([@domain.registrant.email] + @domain.admin_contacts.map { |x| format(x.email) })
@params[:recipient] = emails.uniq.map { |x| format(x) }
end
# puny internet domain name, TODO: username<email>
def format(email)
return warn_no_email if email.nil?
user, host = email.split('@')
host = SimpleIDN.to_ascii(host)
"#{user}@#{host}"
end
def subject(subject)
@params[:name] = @domain.name
@params[:subject] = "#{I18n.t(subject, name: @domain.name)}, [#{@domain.name}]"
end
def confirm_update
verification_url('domain_update_confirms')
end
def confirm_delete
verification_url('domain_delete_confirms')
end
def compose
@params
end
def verification_url(path)
token = verification_token or return
@params[:verification_url] = "#{ENV['registrant_url']}/registrant/#{path}/#{@domain.id}?token=#{token}"
end
def verification_token
return warn_missing(:registrant_verification_token) if @domain.registrant_verification_token.blank?
return warn_missing(:registrant_verification_asked_at) if @domain.registrant_verification_asked_at.blank?
@domain.registrant_verification_token
end
def domain_info
[:name, :registrar_name,
:registrant_name, :registrant_ident, :registrant_email,
:registrant_street,:registrant_city
].each do |attr|
@params.store attr, @domain.send(attr)
end
@params.store :registrant_country, @domain.registrant_country.name
@params.store :registrant_priv, @domain.registrant.priv?
@params.store :old_registrant_name, Registrant.find(@domain.registrant_id_was).name
@params
end
def warn_no_email(item = 'email')
warn_missing item
nil
end
def warn_missing(item)
warn_not_delivered "#{item.to_s} is missing for #{@domain.name}"
end
def warn_not_delivered(reason)
message = "EMAIL NOT DELIVERED: #{reason}"
@params[:errors] << message
# Rails.logger.warn message
nil
end
end

View file

@ -5,6 +5,7 @@ class Epp::Contact < Contact
self.inheritance_column = :sti_disabled
before_validation :manage_permissions
def manage_permissions
return unless update_prohibited? || delete_prohibited?
add_epp_error('2304', nil, nil, I18n.t(:object_status_prohibits_operation))
@ -36,10 +37,7 @@ class Epp::Contact < Contact
at[:country_code] = f.css('postalInfo addr cc').text if f.css('postalInfo addr cc').present?
at[:auth_info] = f.css('authInfo pw').text if f.css('authInfo pw').present?
legal_frame = f.css('legalDocument').first
if legal_frame.present?
at[:legal_documents_attributes] = legal_document_attrs(legal_frame)
end
at.merge!(ident_attrs(f.css('ident').first)) if new_record
at
end
@ -103,6 +101,7 @@ class Epp::Contact < Contact
res
end
end
delegate :ident_attr_valid?, to: :class
@ -123,6 +122,7 @@ class Epp::Contact < Contact
[:email, :invalid],
[:ident, :invalid],
[:ident, :invalid_EE_identity_format],
[:ident, :invalid_EE_identity_format_update],
[:ident, :invalid_birthday_format],
[:ident, :invalid_country_code],
[:ident_type, :missing],
@ -132,6 +132,9 @@ class Epp::Contact < Contact
'2302' => [ # Object exists
[:code, :epp_id_taken]
],
'2304' => [ # Object status prohibits operation
[:ident_type, :epp_ident_type_invalid, { value: { obj: 'code', val: code}, interpolation: {code: code}}]
],
'2305' => [ # Association exists
[:domains, :exist]
],
@ -141,7 +144,7 @@ class Epp::Contact < Contact
end
# rubocop:disable Metrics/AbcSize
def update_attributes(frame)
def update_attributes(frame, current_user)
return super if frame.blank?
at = {}.with_indifferent_access
at.deep_merge!(self.class.attrs_from(frame.css('chg'), new_record: false))
@ -150,8 +153,14 @@ class Epp::Contact < Contact
at[:statuses] = statuses - statuses_attrs(frame.css('rem'), 'rem') + statuses_attrs(frame.css('add'), 'add')
end
legal_frame = frame.css('legalDocument').first
at[:legal_documents_attributes] = self.class.legal_document_attrs(legal_frame)
# legal_frame = frame.css('legalDocument').first
# at[:legal_documents_attributes] = self.class.legal_document_attrs(legal_frame)
if doc = attach_legal_document(Epp::Domain.parse_legal_document_from_frame(frame))
frame.css("legalDocument").first.content = doc.path if doc && doc.persisted?
self.legal_document_id = doc.id
end
self.deliver_emails = true # turn on email delivery for epp
@ -160,21 +169,28 @@ class Epp::Contact < Contact
self.ident_updated_at ||= Time.zone.now # not in use
ident_frame = frame.css('ident').first
if ident_frame && ident_attr_valid?(ident_frame) && ident_country_code.blank? && ident_type.in?(%w(org priv).freeze)
if ident_frame && ident_attr_valid?(ident_frame)
org_priv = %w(org priv).freeze
if ident_country_code.blank? && org_priv.include?(ident_type) && org_priv.include?(ident_frame.attr('type'))
at.merge!(ident_country_code: ident_frame.attr('cc'), ident_type: ident_frame.attr('type'))
elsif ident_type == "birthday" && !ident[/\A\d{4}-\d{2}-\d{2}\z/] && (Date.parse(ident) rescue false)
at.merge!(ident: ident_frame.text)
at.merge!(ident_country_code: ident_frame.attr('cc')) if ident_frame.attr('cc').present?
elsif ident_type == "birthday" && ident_country_code.blank?
at.merge!(ident_country_code: ident_frame.attr('cc'))
elsif ident_type.blank? && ident_country_code.blank?
at.merge!(ident_type: ident_frame.attr('type'))
at.merge!(ident_country_code: ident_frame.attr('cc')) if ident_frame.attr('cc').present?
else
throw :epp_error, {code: '2306', msg: I18n.t(:ident_update_error)}
end
else
throw :epp_error, {code: '2306', msg: I18n.t(:ident_update_error)}
end
end
# Deprecated
# if ident_updated_at.present?
# throw :epp_error, {
# code: '2306',
# msg: I18n.t(:ident_update_error)
# }
# else
# at.merge!(self.class.ident_attrs(frame.css('ident').first))
# self.ident_updated_at = Time.zone.now
# end
end
self.upid = current_user.registrar.id if current_user.registrar
self.up_date = Time.zone.now
super(at)
end
@ -213,4 +229,29 @@ class Epp::Contact < Contact
status_list
end
def attach_legal_document(legal_document_data)
return unless legal_document_data
legal_documents.create(
document_type: legal_document_data[:type],
body: legal_document_data[:body]
)
end
def add_legal_file_to_new frame
legal_document_data = Epp::Domain.parse_legal_document_from_frame(frame)
return unless legal_document_data
doc = LegalDocument.create(
documentable_type: Contact,
document_type: legal_document_data[:type],
body: legal_document_data[:body]
)
self.legal_documents = [doc]
frame.css("legalDocument").first.content = doc.path if doc && doc.persisted?
self.legal_document_id = doc.id
end
end

View file

@ -3,10 +3,13 @@ class Epp::Domain < Domain
include EppErrors
# TODO: remove this spagetti once data in production is correct.
attr_accessor :is_renewal
attr_accessor :is_renewal, :is_transfer
before_validation :manage_permissions
def manage_permissions
return if is_admin # this bad hack for 109086524, refactor later
return true if is_transfer || is_renewal
return unless update_prohibited? || delete_prohibited?
add_epp_error('2304', nil, nil, I18n.t(:object_status_prohibits_operation))
false
@ -14,7 +17,7 @@ class Epp::Domain < Domain
after_validation :validate_contacts
def validate_contacts
return true if is_renewal
return true if is_renewal || is_transfer
ok = true
active_admins = admin_domain_contacts.select { |x| !x.marked_for_destruction? }
@ -130,7 +133,8 @@ class Epp::Domain < Domain
[:base, :ds_data_not_allowed],
[:base, :key_data_not_allowed],
[:period, :not_a_number],
[:period, :not_an_integer]
[:period, :not_an_integer],
[:registrant, :cannot_be_missing]
],
'2308' => [
[:base, :domain_name_blocked, { value: { obj: 'name', val: name_dirty } }]
@ -152,7 +156,8 @@ class Epp::Domain < Domain
def attrs_from(frame, current_user, action = nil)
at = {}.with_indifferent_access
code = frame.css('registrant').first.try(:text)
registrant_frame = frame.css('registrant').first
code = registrant_frame.try(:text)
if code.present?
if action == 'chg' && registrant_change_prohibited?
add_epp_error('2304', nil, DomainStatus::SERVER_REGISTRANT_CHANGE_PROHIBITED, I18n.t(:object_status_prohibits_operation))
@ -163,7 +168,10 @@ class Epp::Domain < Domain
else
add_epp_error('2303', 'registrant', code, [:registrant, :not_found])
end
end
else
add_epp_error('2306', nil, nil, [:registrant, :cannot_be_missing])
end if registrant_frame
at[:name] = frame.css('name').text if new_record?
at[:registrar_id] = current_user.registrar.try(:id)
@ -192,9 +200,27 @@ class Epp::Domain < Domain
end
at[:dnskeys_attributes] = dnskeys_attrs(dnskey_frame, action)
at[:legal_documents_attributes] = legal_document_from(frame)
at
end
# Adding legal doc to domain and
# if something goes wrong - raise Rollback error
def add_legal_file_to_new frame
legal_document_data = Epp::Domain.parse_legal_document_from_frame(frame)
return unless legal_document_data
doc = LegalDocument.create(
documentable_type: Domain,
document_type: legal_document_data[:type],
body: legal_document_data[:body]
)
self.legal_documents = [doc]
frame.css("legalDocument").first.content = doc.path if doc && doc.persisted?
self.legal_document_id = doc.id
end
# rubocop: enable Metrics/PerceivedComplexity
# rubocop: enable Metrics/CyclomaticComplexity
# rubocop: enable Metrics/MethodLength
@ -454,15 +480,6 @@ class Epp::Domain < Domain
status_list
end
def legal_document_from(frame)
ld = frame.css('legalDocument').first
return [] unless ld
[{
body: ld.text,
document_type: ld['type']
}]
end
# rubocop: disable Metrics/AbcSize
# rubocop: disable Metrics/CyclomaticComplexity
@ -474,6 +491,7 @@ class Epp::Domain < Domain
if doc = attach_legal_document(Epp::Domain.parse_legal_document_from_frame(frame))
frame.css("legalDocument").first.content = doc.path if doc && doc.persisted?
self.legal_document_id = doc.id
end
at_add = attrs_from(frame.css('add'), current_user, 'add')
@ -486,6 +504,20 @@ class Epp::Domain < Domain
# at[:statuses] += at_add[:domain_statuses_attributes]
if errors.empty? && verify
self.upid = current_user.registrar.id if current_user.registrar
self.up_date = Time.zone.now
end
if registrant_id && registrant.code == frame.css('registrant')
throw :epp_error, {
code: '2305',
msg: I18n.t(:contact_already_associated_with_the_domain)
}
end
if errors.empty? && verify &&
Setting.request_confrimation_on_registrant_change_enabled &&
frame.css('registrant').present? &&
@ -500,18 +532,26 @@ class Epp::Domain < Domain
# rubocop: enable Metrics/CyclomaticComplexity
def apply_pending_update!
old_registrant_email = DomainMailer.registrant_updated_notification_for_old_registrant(id, deliver_emails)
preclean_pendings
user = ApiUser.find(pending_json['current_user_id'])
frame = Nokogiri::XML(pending_json['frame'])
statuses.delete(DomainStatus::PENDING_UPDATE)
yield(self) if block_given? # need to skip statuses check here
old_registrant_id = registrant_id
self.deliver_emails = true # turn on email delivery
self.statuses.delete(DomainStatus::PENDING_UPDATE)
self.upid = user.registrar.id if user.registrar
self.up_date = Time.zone.now
::PaperTrail.whodunnit = user.id_role_username # updator str should be the request originator not the approval user
return unless update(frame, user, false)
clean_pendings!
self.deliver_emails = true # turn on email delivery
DomainMailer.registrant_updated_notification_for_new_registrant(id, deliver_emails).deliver
old_registrant_email.deliver
save! # for notification if everything fails
WhoisRecord.find_by(domain_id: id).save # need to reload model
DomainMailer.registrant_updated_notification_for_old_registrant(id, old_registrant_id, registrant_id, true).deliver
DomainMailer.registrant_updated_notification_for_new_registrant(id, old_registrant_id, registrant_id, true).deliver
true
end
@ -560,7 +600,7 @@ class Epp::Domain < Domain
msg: I18n.t(:object_status_prohibits_operation)
} unless pending_deletable?
self.delete_at = Time.zone.now + Setting.redemption_grace_period.days
self.delete_at = (Time.zone.now + (Setting.redemption_grace_period.days + 1.day)).utc.beginning_of_day
set_pending_delete
set_server_hold if server_holdable?
save(validate: false)
@ -584,6 +624,7 @@ class Epp::Domain < Domain
statuses.delete(DomainStatus::SERVER_HOLD)
statuses.delete(DomainStatus::EXPIRED)
statuses.delete(DomainStatus::SERVER_UPDATE_PROHIBITED)
save
end
@ -592,6 +633,8 @@ class Epp::Domain < Domain
# rubocop: disable Metrics/CyclomaticComplexity
def transfer(frame, action, current_user)
@is_transfer = true
case action
when 'query'
return domain_transfers.last if domain_transfers.any?
@ -619,6 +662,7 @@ class Epp::Domain < Domain
oc.registrar_id = registrar_id
oc.copy_from_id = c.id
oc.prefix_code
oc.domain_transfer = true
oc.save!(validate: false)
oc
end
@ -849,6 +893,7 @@ class Epp::Domain < Domain
ld = parsed_frame.css('legalDocument').first
return nil unless ld
return nil if ld.text.starts_with?(ENV['legal_documents_dir']) # escape reloading
return nil if ld.text.starts_with?('/home/') # escape reloading
{
body: ld.text,

View file

@ -2,14 +2,27 @@ class Invoice < ActiveRecord::Base
include Versions
belongs_to :seller, class_name: 'Registrar'
belongs_to :buyer, class_name: 'Registrar'
has_many :invoice_items
has_one :account_activity
has_many :invoice_items
has_many :directo_records, as: :item, class_name: 'Directo'
accepts_nested_attributes_for :invoice_items
scope :unbinded, lambda {
where('id NOT IN (SELECT invoice_id FROM account_activities where invoice_id IS NOT NULL)')
}
scope :all_columns, ->{select("invoices.*")}
scope :sort_due_date_column, ->{all_columns.select("CASE WHEN invoices.cancelled_at is not null THEN
(invoices.cancelled_at + interval '100 year') ELSE
invoices.due_date END AS sort_due_date")}
scope :sort_by_sort_due_date_asc, ->{sort_due_date_column.order("sort_due_date ASC")}
scope :sort_by_sort_due_date_desc, ->{sort_due_date_column.order("sort_due_date DESC")}
scope :sort_receipt_date_column, ->{all_columns.includes(:account_activity).references(:account_activity).select(%Q{
CASE WHEN account_activities.created_at is not null THEN account_activities.created_at
WHEN invoices.cancelled_at is not null THEN invoices.cancelled_at + interval '100 year'
ELSE NULL END AS sort_receipt_date })}
scope :sort_by_sort_receipt_date_asc, ->{sort_receipt_date_column.order("sort_receipt_date ASC")}
scope :sort_by_sort_receipt_date_desc, ->{sort_receipt_date_column.order("sort_receipt_date DESC")}
attr_accessor :billing_email
validates :billing_email, email_format: { message: :invalid }, allow_blank: true
@ -17,7 +30,10 @@ class Invoice < ActiveRecord::Base
validates :invoice_type, :due_date, :currency, :seller_name,
:seller_iban, :buyer_name, :invoice_items, :vat_prc, presence: true
before_create :set_invoice_number
before_create :set_invoice_number, :check_vat
before_save :check_vat
def set_invoice_number
last_no = Invoice.order(number: :desc).where('number IS NOT NULL').limit(1).pluck(:number).first
@ -34,6 +50,12 @@ class Invoice < ActiveRecord::Base
false
end
def check_vat
if buyer.country_code != 'EE' && buyer.vat_no.present?
self.vat_prc = 0
end
end
before_save -> { self.sum_cache = sum }
class << self
@ -90,6 +112,10 @@ class Invoice < ActiveRecord::Base
kit.to_pdf
end
def description
"Order nr. #{number}"
end
def pdf_name
"invoice-#{number}.pdf"
end

View file

@ -1,4 +1,7 @@
class LegalDocument < ActiveRecord::Base
include EppErrors
MIN_BODY_SIZE = (1.37 * 3.kilobytes).ceil
if ENV['legal_document_types'].present?
TYPES = ENV['legal_document_types'].split(',').map(&:strip)
else
@ -9,9 +12,23 @@ class LegalDocument < ActiveRecord::Base
belongs_to :documentable, polymorphic: true
validate :val_body_length, if: ->(file){ file.path.blank? && !Rails.env.staging?}
before_create :add_creator
before_save :save_to_filesystem
def epp_code_map
{
'2306' => [
[:body, :length]
]
}
end
def val_body_length
errors.add(:body, :length) if body.nil? || body.size < MIN_BODY_SIZE
end
def save_to_filesystem

View file

@ -8,7 +8,7 @@ class Nameserver < ActiveRecord::Base
# scope :owned_by_registrar, -> (registrar) { joins(:domain).where('domains.registrar_id = ?', registrar.id) }
# rubocop: disable Metrics/LineLength
validates :hostname, format: { with: /\A(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\z/ }
validates :hostname, format: { with: /\A(([a-zA-Z0-9]|[a-zA-ZäöüõšžÄÖÜÕŠŽ0-9][a-zA-ZäöüõšžÄÖÜÕŠŽ0-9\-]*[a-zA-ZäöüõšžÄÖÜÕŠŽ0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])\z/ }
# validates :ipv4, format: { with: /\A(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\z/, allow_blank: true }
# validates :ipv6, format: { with: /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/, allow_blank: true }
validate :val_ipv4
@ -16,6 +16,8 @@ class Nameserver < ActiveRecord::Base
# rubocop: enable Metrics/LineLength
before_validation :normalize_attributes
before_validation :check_puny_symbols
before_validation :check_label_length
delegate :name, to: :domain, prefix: true
@ -26,6 +28,7 @@ class Nameserver < ActiveRecord::Base
],
'2005' => [
[:hostname, :invalid, { value: { obj: 'hostAttr', val: hostname } }],
[:hostname, :puny_to_long, { value: { obj: 'hostAttr', val: hostname } }],
[:ipv4, :invalid, { value: { obj: 'hostAddr', val: ipv4 } }],
[:ipv6, :invalid, { value: { obj: 'hostAddr', val: ipv6 } }]
],
@ -41,10 +44,26 @@ class Nameserver < ActiveRecord::Base
self.ipv6 = Array(ipv6).reject(&:blank?).map(&:strip).map(&:upcase)
end
def check_label_length
hostname_puny.split('.').each do |label|
errors.add(:hostname, :puny_to_long) if label.length > 63
end
end
def check_puny_symbols
regexp = /(\A|\.)..--/
errors.add(:hostname, :invalid) if hostname =~ regexp
end
def to_s
hostname
end
def hostname=(hostname)
self[:hostname] = SimpleIDN.to_unicode(hostname)
self[:hostname_puny] = SimpleIDN.to_ascii(hostname)
end
def val_ipv4
regexp = /\A(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\z/
ipv4.to_a.each do |ip|

View file

@ -8,6 +8,8 @@ class Pricelist < ActiveRecord::Base
)
}
scope :valid_at, ->(time){ where("valid_from IS NULL OR valid_from <= ?", time).where("valid_to IS NULL OR valid_to >= ?", time) }
monetize :price_cents
validates :price_cents, :price_currency, :price,
@ -27,11 +29,19 @@ class Pricelist < ActiveRecord::Base
"#{operation_category} #{category}"
end
def years_amount
duration.to_i
end
def price_decimal
price_cents / BigDecimal.new('100')
end
class << self
def pricelist_for(zone, operation, period)
lists = valid.where(category: zone, operation_category: operation, duration: period)
return lists.first if lists.count == 1
lists.where('valid_to IS NOT NULL').order(valid_from: :desc).first
lists.order(valid_from: :desc).first
end
end
end

View file

@ -1,4 +1,5 @@
class RegistrantUser < User
ACCEPTED_ISSUER = 'AS Sertifitseerimiskeskus'
attr_accessor :idc_data
def ability
@ -6,6 +7,19 @@ class RegistrantUser < User
end
delegate :can?, :cannot?, to: :ability
def ident
registrant_ident.to_s.split("-").last
end
def domains
ident_cc, ident = registrant_ident.to_s.split '-'
Domain.includes(:registrar, :registrant).where(contacts: {
ident_type: 'priv',
ident: ident, #identity_code,
ident_country_code: ident_cc #country_code
})
end
def to_s
username
end
@ -13,15 +27,23 @@ class RegistrantUser < User
class << self
def find_or_create_by_idc_data(idc_data, issuer_organization)
return false if idc_data.blank?
return false if issuer_organization != 'AS Sertifitseerimiskeskus'
return false if issuer_organization != ACCEPTED_ISSUER
idc_data.force_encoding('UTF-8')
logger.error(idc_data)
logger.error(idc_data.encoding)
# handling here new and old mode
if idc_data.starts_with?("/")
identity_code = idc_data.scan(/serialNumber=(\d+)/).flatten.first
country = idc_data.scan(/^\/C=(.{2})/).flatten.first
first_name = idc_data.scan(%r{/GN=(.+)/serialNumber}).flatten.first
last_name = idc_data.scan(%r{/SN=(.+)/GN}).flatten.first
else
parse_str = "," + idc_data
identity_code = parse_str.scan(/,serialNumber=(\d+)/).flatten.first
country = parse_str.scan(/,C=(.{2})/).flatten.first
first_name = parse_str.scan(/,GN=([^,]+)/).flatten.first
last_name = parse_str.scan(/,SN=([^,]+)/).flatten.first
end
u = where(registrant_ident: "#{country}-#{identity_code}").first_or_create
u.username = "#{first_name} #{last_name}"

View file

@ -12,7 +12,6 @@ class RegistrantVerification < ActiveRecord::Base
belongs_to :domain
validates :verification_token, :domain_name, :domain, :action, :action_type, presence: true
validates :domain, uniqueness: { scope: [:domain_id, :verification_token] }
def domain_registrant_change_confirm!
self.action_type = DOMAIN_REGISTRANT_CHANGE
@ -23,7 +22,7 @@ class RegistrantVerification < ActiveRecord::Base
def domain_registrant_change_reject!
self.action_type = DOMAIN_REGISTRANT_CHANGE
self.action = REJECTED
DomainUpdateConfirmJob.enqueue domain.id, REJECTED if save
DomainUpdateConfirmJob.run domain.id, REJECTED if save
end
def domain_registrant_delete_confirm!

View file

@ -1,25 +1,76 @@
class ReservedDomain < ActiveRecord::Base
include Versions # version/reserved_domain_version.rb
before_save :fill_empty_passwords
before_save :generate_data
after_destroy :remove_data
validates :name, domain_name: true, uniqueness: true
def fill_empty_passwords
return unless names
names.each { |k, v| names[k] = SecureRandom.hex if v.blank? }
end
class << self
def pw_for(domain_name)
name_in_unicode = SimpleIDN.to_ascii(domain_name)
by_domain(domain_name).select("names -> '#{domain_name}' AS pw").first.try(:pw) ||
by_domain(name_in_unicode).select("names -> '#{name_in_unicode}' AS pw").first.try(:pw)
name_in_ascii = SimpleIDN.to_ascii(domain_name)
by_domain(domain_name).first.try(:password) || by_domain(name_in_ascii).first.try(:password)
end
def by_domain name
where("names ? '#{name}'")
where(name: name)
end
def any_of_domains names
where("names ?| ARRAY['#{names.join("','")}']")
where(name: names)
end
def new_password_for name
record = by_domain(name).first
return unless record
record.regenerate_password
record.save
end
end
def name= val
super SimpleIDN.to_unicode(val)
end
def fill_empty_passwords
regenerate_password if self.password.blank?
end
def regenerate_password
self.password = SecureRandom.hex
end
def generate_data
return if Domain.where(name: name).any?
wr = Whois::Record.find_or_initialize_by(name: name)
wr.json = @json = generate_json # we need @json to bind to class
wr.body = generate_body
wr.save
end
alias_method :update_whois_record, :generate_data
def generate_body
template = Rails.root.join("app/views/for_models/whois_other.erb".freeze)
ERB.new(template.read, nil, "-").result(binding)
end
def generate_json
h = HashWithIndifferentAccess.new
h[:name] = self.name
h[:status] = ['Reserved']
h
end
def remove_data
UpdateWhoisRecordJob.enqueue name, 'reserved'
end
end

219
app/models/soap/arireg.rb Normal file
View file

@ -0,0 +1,219 @@
# coding: utf-8
require 'savon'
=begin
Estonian Business registry provides information about registered companies via xml (SOAP over HTTPS).
Note:
The SSL endpoint certificate is self signed.
Documentation:
http://www.rik.ee/et/e-ariregister/xml-teenus
Specifications are in Eng and Est
User contract required
Testing:
https://demo-ariregxml.rik.ee:447/testariport/?wsdl
http://demo-ariregxml.rik.ee:81
https://demo-ariregxml.rik.ee:447
Live service:
https://ariregxml.rik.ee/ariport/?wsdl
https://ariregxml.rik.ee/
Implements Soap::Arireg # associated_businesses
8. arireg.paringesindus_v4
Rights of representation of all persons related to the company (newer)
http://www2.rik.ee/schemas/xtee/arireg/live/paringesindus_v4.xsd
expects personal id code, to fetch list of registered business id codes
returning {ident: person, ident_country_code: ... associated_businesses: [...id_codes...]}
=end
# do some SSL set up?
# ssl_version
# ssl_verify_mode
# ssl_cert_key_file
# ssl_cert_key
# ssl_cert_key_password
# ssl_cert_file
# ssl_cert
# ssl_ca_cert_file
# ssl_ca_cert
module Soap
class Arireg
class NotAvailableError < StandardError
attr_accessor :json
def initialize(params)
params[:message] = "#{I18n.t(:business_registry_service_not_available)}" unless params.key? :message
@json = params
super(params)
end
end
class << self
attr_accessor :wsdl, :host, :username, :password
end
def initialize
if self.class.username.nil?
if Rails.application.secrets.key?(:arireg)
arireg = Rails.application.secrets[:arireg].with_indifferent_access
self.class.username = arireg[:username]
self.class.password = arireg[:password]
if self.class.wsdl.nil? # no override of config/environments/* ?
self.class.wsdl = arireg[:wsdl]
self.class.host = arireg[:host]
end
else
self.class.username = ENV['arireg_username']
self.class.password = ENV['arireg_password']
end
end
if self.class.wsdl.nil?
self.class.wsdl = ENV['arireg_wsdl']
self.class.host = ENV['arireg_host']
end
# note Savon has error if https w/non-standard port,
# use non-standard force to pre-set endpoint
@client = Savon.client(wsdl: self.class.wsdl,
host: self.class.host,
endpoint: "#{self.class.host}/cgi-bin/consumer_proxy")
@session = nil
end
# retrieve business id codes for business that a person has a legal role
def associated_businesses(ident, ident_cc = 'EST')
begin
msg = {
'fyysilise_isiku_kood' => ident,
'fyysilise_isiku_koodi_riik' => country_code_3(ident_cc)
}
Rails.logger.info "[Ariregister] Request sent with data: #{msg.inspect}"
response = @client.call :paringesindus_v4, message: body(msg)
content = extract response, :paringesindus_v4_response
Rails.logger.info "[Ariregister] Got response with data: #{content.inspect}"
if content.present? && content[:ettevotjad].key?(:item)
business_ident = items(content, :ettevotjad).map{|item| item[:ariregistri_kood]}
else
business_ident = []
end
{
ident: ident,
ident_country_code: ident_cc,
# ident_type: 'priv',
retrieved_on: Time.now,
associated_businesses: business_ident
}
rescue Savon::SOAPFault => fault
Rails.logger.error "[Ariregister] #{fault} Äriregister arireg #{self.class.username} at #{self.class.host }"
raise NotAvailableError.new(exception: fault)
rescue HTTPI::SSLError => ssl_error
Rails.logger.error "[Ariregister] #{ssl_error} at #{self.class.host}"
raise NotAvailableError.new(exception: ssl_error)
rescue SocketError => sock
Rails.logger.error "[Ariregister] #{sock}"
raise NotAvailableError.new(exception: sock)
end
end
def debug
@client.globals.log_level :debug
@client.globals.log true
@client.globals.pretty_print_xml true
@debug = true
@client
end
private
# add required elements to request
def body(args)
if @session.nil?
args['ariregister_kasutajanimi'] = self.class.username
args['ariregister_parool'] = self.class.password
else
args['ariregister_sessioon'] = @session
end
{keha: args}
end
# TLA --- three letter acronym required not two letter acronym, transform
def country_code_3(code)
if code.length == 2
code = CC2X3[code]
raise NotAvailableError.new(message: 'Unrecognized Country') if code.nil?
end
code
end
def extract(response, element)
# response envelope body has again header/body under element; header is user and password returned
response.hash[:envelope][:body][element][:keha]
end
def items(content, parent)
items = content[parent][:item]
items.is_a?(Array) ? items : [items]
end
CC2X3 = {"AF"=>"AFG", "AX"=>"ALA", "AL"=>"ALB", "DZ"=>"DZA", "AS"=>"ASM",
"AD"=>"AND", "AO"=>"AGO", "AI"=>"AIA", "AQ"=>"ATA", "AG"=>"ATG",
"AR"=>"ARG", "AM"=>"ARM", "AW"=>"ABW", "AU"=>"AUS", "AT"=>"AUT",
"AZ"=>"AZE", "BS"=>"BHS", "BH"=>"BHR", "BD"=>"BGD", "BB"=>"BRB",
"BY"=>"BLR", "BE"=>"BEL", "BZ"=>"BLZ", "BJ"=>"BEN", "BM"=>"BMU",
"BT"=>"BTN", "BO"=>"BOL", "BQ"=>"BES", "BA"=>"BIH", "BW"=>"BWA",
"BV"=>"BVT", "BR"=>"BRA", "IO"=>"IOT", "BN"=>"BRN", "BG"=>"BGR",
"BF"=>"BFA", "BI"=>"BDI", "CV"=>"CPV", "KH"=>"KHM", "CM"=>"CMR",
"CA"=>"CAN", "KY"=>"CYM", "CF"=>"CAF", "TD"=>"TCD", "CL"=>"CHL",
"CN"=>"CHN", "CX"=>"CXR", "CC"=>"CCK", "CO"=>"COL", "KM"=>"COM",
"CD"=>"COD", "CG"=>"COG", "CK"=>"COK", "CR"=>"CRI", "CI"=>"CIV",
"HR"=>"HRV", "CU"=>"CUB", "CW"=>"CUW", "CY"=>"CYP", "CZ"=>"CZE",
"DK"=>"DNK", "DJ"=>"DJI", "DM"=>"DMA", "DO"=>"DOM", "EC"=>"ECU",
"EG"=>"EGY", "SV"=>"SLV", "GQ"=>"GNQ", "ER"=>"ERI", "EE"=>"EST",
"ET"=>"ETH", "FK"=>"FLK", "FO"=>"FRO", "FJ"=>"FJI", "FI"=>"FIN",
"FR"=>"FRA", "GF"=>"GUF", "PF"=>"PYF", "TF"=>"ATF", "GA"=>"GAB",
"GM"=>"GMB", "GE"=>"GEO", "DE"=>"DEU", "GH"=>"GHA", "GI"=>"GIB",
"GR"=>"GRC", "GL"=>"GRL", "GD"=>"GRD", "GP"=>"GLP", "GU"=>"GUM",
"GT"=>"GTM", "GG"=>"GGY", "GN"=>"GIN", "GW"=>"GNB", "GY"=>"GUY",
"HT"=>"HTI", "HM"=>"HMD", "VA"=>"VAT", "HN"=>"HND", "HK"=>"HKG",
"HU"=>"HUN", "IS"=>"ISL", "IN"=>"IND", "ID"=>"IDN", "IR"=>"IRN",
"IQ"=>"IRQ", "IE"=>"IRL", "IM"=>"IMN", "IL"=>"ISR", "IT"=>"ITA",
"JM"=>"JAM", "JP"=>"JPN", "JE"=>"JEY", "JO"=>"JOR", "KZ"=>"KAZ",
"KE"=>"KEN", "KI"=>"KIR", "KP"=>"PRK", "KR"=>"KOR", "KW"=>"KWT",
"KG"=>"KGZ", "LA"=>"LAO", "LV"=>"LVA", "LB"=>"LBN", "LS"=>"LSO",
"LR"=>"LBR", "LY"=>"LBY", "LI"=>"LIE", "LT"=>"LTU", "LU"=>"LUX",
"MO"=>"MAC", "MK"=>"MKD", "MG"=>"MDG", "MW"=>"MWI", "MY"=>"MYS",
"MV"=>"MDV", "ML"=>"MLI", "MT"=>"MLT", "MH"=>"MHL", "MQ"=>"MTQ",
"MR"=>"MRT", "MU"=>"MUS", "YT"=>"MYT", "MX"=>"MEX", "FM"=>"FSM",
"MD"=>"MDA", "MC"=>"MCO", "MN"=>"MNG", "ME"=>"MNE", "MS"=>"MSR",
"MA"=>"MAR", "MZ"=>"MOZ", "MM"=>"MMR", "NA"=>"NAM", "NR"=>"NRU",
"NP"=>"NPL", "NL"=>"NLD", "NC"=>"NCL", "NZ"=>"NZL", "NI"=>"NIC",
"NE"=>"NER", "NG"=>"NGA", "NU"=>"NIU", "NF"=>"NFK", "MP"=>"MNP",
"NO"=>"NOR", "OM"=>"OMN", "PK"=>"PAK", "PW"=>"PLW", "PS"=>"PSE",
"PA"=>"PAN", "PG"=>"PNG", "PY"=>"PRY", "PE"=>"PER", "PH"=>"PHL",
"PN"=>"PCN", "PL"=>"POL", "PT"=>"PRT", "PR"=>"PRI", "QA"=>"QAT",
"RE"=>"REU", "RO"=>"ROU", "RU"=>"RUS", "RW"=>"RWA", "BL"=>"BLM",
"SH"=>"SHN", "KN"=>"KNA", "LC"=>"LCA", "MF"=>"MAF", "PM"=>"SPM",
"VC"=>"VCT", "WS"=>"WSM", "SM"=>"SMR", "ST"=>"STP", "SA"=>"SAU",
"SN"=>"SEN", "RS"=>"SRB", "SC"=>"SYC", "SL"=>"SLE", "SG"=>"SGP",
"SX"=>"SXM", "SK"=>"SVK", "SI"=>"SVN", "SB"=>"SLB", "SO"=>"SOM",
"ZA"=>"ZAF", "GS"=>"SGS", "SS"=>"SSD", "ES"=>"ESP", "LK"=>"LKA",
"SD"=>"SDN", "SR"=>"SUR", "SJ"=>"SJM", "SZ"=>"SWZ", "SE"=>"SWE",
"CH"=>"CHE", "SY"=>"SYR", "TW"=>"TWN", "TJ"=>"TJK", "TZ"=>"TZA",
"TH"=>"THA", "TL"=>"TLS", "TG"=>"TGO", "TK"=>"TKL", "TO"=>"TON",
"TT"=>"TTO", "TN"=>"TUN", "TR"=>"TUR", "TM"=>"TKM", "TC"=>"TCA",
"TV"=>"TUV", "UG"=>"UGA", "UA"=>"UKR", "AE"=>"ARE", "GB"=>"GBR",
"UM"=>"UMI", "US"=>"USA", "UY"=>"URY", "UZ"=>"UZB", "VU"=>"VUT",
"VE"=>"VEN", "VN"=>"VNM", "VG"=>"VGB", "VI"=>"VIR", "WF"=>"WLF",
"EH"=>"ESH", "YE"=>"YEM", "ZM"=>"ZMB", "ZW"=>"ZWE"}
end
end

View file

@ -3,4 +3,9 @@ class User < ActiveRecord::Base
devise :trackable, :timeoutable
attr_accessor :phone
def id_role_username
"#{self.id}-#{self.class}: #{self.username}"
end
end

View file

@ -3,7 +3,5 @@ class ContactVersion < PaperTrail::Version
self.table_name = :log_contacts
self.sequence_name = :log_contacts_id_seq
# include UserEvents
# scope :deleted, -> { where(event: 'destroy') }
end

View file

@ -4,7 +4,5 @@ class DomainVersion < PaperTrail::Version
self.table_name = :log_domains
self.sequence_name = :log_domains_id_seq
include UserEvents
scope :deleted, -> { where(event: 'destroy') }
end

View file

@ -23,6 +23,10 @@ class WhoisRecord < ActiveRecord::Base
end
end
def self.find_by_name(name)
WhoisRecord.where("lower(name) = ?", name.downcase)
end
def generated_json
@generated_json ||= generate_json
end
@ -44,11 +48,11 @@ class WhoisRecord < ActiveRecord::Base
h[:changed] = domain.updated_at.try(:to_s, :iso8601)
h[:expire] = domain.valid_to.try(:to_date).try(:to_s)
h[:outzone] = domain.outzone_at.try(:to_date).try(:to_s)
h[:delete] = domain.delete_at.try(:to_date).try(:to_s)
h[:delete] = [domain.delete_at, domain.force_delete_at].compact.min.try(:to_date).try(:to_s)
h[:registrant] = domain.registrant.name
h[:registrant_email] = domain.registrant.email
h[:email] = domain.registrant.email
@disclosed << [:email, domain.registrant.email]
h[:registrant_changed] = domain.registrant.updated_at.try(:to_s, :iso8601)
@ -102,7 +106,7 @@ class WhoisRecord < ActiveRecord::Base
self.json = generated_json
self.body = generated_body
self.name = json['name']
self.registrar_id = domain.registrar_id # for faster registrar updates
self.registrar_id = domain.registrar_id if domain # for faster registrar updates
end
def update_whois_server
@ -113,6 +117,6 @@ class WhoisRecord < ActiveRecord::Base
end
def destroy_whois_record
Whois::Record.where(name: name).delete_all()
Whois::Record.where(name: name).delete_all
end
end

View file

@ -29,13 +29,24 @@
.form-group
= f.label t(:receipt_date_until)
= f.search_field :created_at_lteq, value: params[:q][:created_at_lteq], class: 'form-control datepicker', placeholder: t(:receipt_date_until), autocomplete: 'off'
.col-md-6{style: 'padding-top: 25px;'}
.col-md-3
.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)
.col-md-3{style: 'padding-top: 25px;'}
%button.btn.btn-default.search
&nbsp;
%span.glyphicon.glyphicon-search
&nbsp;
%button.btn.btn-default.js-reset-form
= t(:clear_fields)
.row
.col-md-3
.col-md-3
.col-md-2
.col-md-4{class: 'text-right'}
= t(:starting_balance) + " #{@sum.to_f} EUR"
%hr
.row
@ -45,7 +56,7 @@
%thead
%tr
%th{class: 'col-xs-2'}
= sort_link(@q, 'registrar')
= sort_link(@q, 'account_registrar_code', t(:registrar))
%th{class: 'col-xs-3'}
= sort_link(@q, 'description')
%th{class: 'col-xs-2'}
@ -55,15 +66,24 @@
%th{class: 'col-xs-2'}
= sort_link(@q, 'sum')
%tbody
-total = @sum.to_f
- @account_activities.each do |x|
%tr
%td= link_to(x.account.registrar.try(:code), admin_registrar_path(x.account.registrar))
%td= x.account.registrar && link_to(x.account.registrar.try(:code), admin_registrar_path(x.account.registrar))
%td= x.description.present? ? x.description : '-'
%td= x.activity_type ? t(x.activity_type) : ''
%td= l(x.created_at)
- c = x.sum > 0.0 ? 'text-success' : 'text-danger'
- s = x.sum > 0.0 ? "+#{x.sum} #{x.currency}" : "#{x.sum} #{x.currency}"
-total += x.sum
%td{class: c}= s
- if @account_activities.count > 0
%tr
%td
%td
%td
%td{class: 'text-right'}= t(:total)
%td{class: total > 0 ? 'text-success' : 'text-danger'}= total > 0 ? "+#{total} EUR" : "#{total} EUR"
.row
.col-md-12
= paginate @account_activities

View file

@ -0,0 +1,17 @@
= form_for([:admin, @domain], html: {class: 'form-horizontal'}) do |f|
= render 'shared/full_errors', object: @domain
.row
.col-md-8
.panel.panel-default
.panel-heading.clearfix
.pull-left= t(:general)
.panel-body
.form-group
.col-md-4.control-label
= f.label :name
.col-md-7
= f.text_field(:name, class: 'form-control')
.row
.col-md-8.text-right
= button_tag(t(:save), class: 'btn btn-primary')

View file

@ -0,0 +1,3 @@
= render 'shared/title', name: t(:edit_pw)
= render 'form'

View file

@ -1,10 +1,68 @@
- content_for :actions do
= link_to(t(:new), new_admin_blocked_domain_path, class: 'btn btn-primary')
= render 'shared/title', name: t(:blocked_domains)
= form_tag([:admin, :blocked_domains]) do |f|
.row
.col-md-12
= text_area_tag :blocked_domains, @blocked_domains, class: 'form-control', rows: 30
= search_form_for [:admin, @q], html: { style: 'margin-bottom: 0;', class: 'js-form', autocomplete: 'off' } do |f|
.row
.col-md-3
.form-group
= f.label :name
= f.search_field :name_matches, value: params[:q][:name_matches], class: 'form-control', placeholder: t(:name)
.col-md-3
.form-group
= f.label t(:created_at_from)
= f.search_field :created_at_gteq, value: params[:q][:created_at_gteq], class: 'form-control datepicker', placeholder: t(:created_at_from)
.col-md-3
.form-group
= f.label t(:created_at_until)
= f.search_field :created_at_lteq, value: params[:q][:created_at_lteq], class: 'form-control datepicker', placeholder: t(:created_at_until)
.row
.col-md-3
.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)
.col-md-3{style: 'padding-top: 25px;'}
%button.btn.btn-primary
&nbsp;
%span.glyphicon.glyphicon-search
&nbsp;
%button.btn.btn-default.js-reset-form
= t(:clear_fields)
%hr
.row
.col-md-12.text-right
%button.btn.btn-warning=t(:save)
.col-md-12
.table-responsive
%table.table.table-hover.table-bordered.table-condensed
%thead
%tr
%th{class: 'col-xs-2'}
= sort_link(@q, 'name')
%th{class: 'col-xs-2'}
= sort_link(@q, 'created_at', t(:created_at))
%th{class: 'col-xs-2'}
= sort_link(@q, 'updated_at', t(:updated_at))
%th{class: 'col-xs-1'}
= t(:actions)
%tbody
- @domains.each do |x|
%tr
%td= x.name
%td= l(x.created_at, format: :short)
%td= l(x.updated_at, format: :short)
%td
%div{class: 'text-center'}
= link_to(t(:delete), delete_admin_blocked_domain_path(id: x.id),
data: { confirm: t(:are_you_sure) }, class: 'btn btn-danger btn-xs')
.row
.col-md-6
= paginate @domains
.col-md-6.text-right
.pagination
= t(:result_count, count: @domains.total_count)
:coffee
$(".js-reset-form").on "click", (e) ->
e.preventDefault();
window.location = "#{admin_blocked_domains_path}"

View file

@ -0,0 +1,3 @@
= render 'shared/title', name: t(:add_blocked_domain)
= render 'form'

View file

@ -1,6 +1,5 @@
- contact = Contact.new(@version.object.to_h)
- @version.object_changes.to_h.each{|k,v| contact[k]=v.last}
= render 'shared/title', name: contact.name
.row
@ -14,62 +13,71 @@
.panel-body
%dl.dl-horizontal
%dt= t(:id)
%dd= contact.code
%dd{class: changing_css_class(@version,"code")}
= contact.code
%dt= t(:statuses)
%dd{class: changing_css_class(@version,"statuses")}
= contact.statuses.join(", ")
%dt= t(:ident)
%dd= ident_for(contact)
%dd{class: changing_css_class(@version,"ident_country_code", "ident_type", "ident")}
= ident_for(contact)
- if contact.email.present?
%dt= t(:email)
%dd= contact.email
%dd{class: changing_css_class(@version,"email")}
= contact.email
- if contact.phone.present?
%dt= t(:phone)
%dd= contact.phone
%dd{class: changing_css_class(@version,"phone")}
= contact.phone
- if contact.fax.present?
%dt= t(:fax)
%dd= contact.fax
%dd{class: changing_css_class(@version,"fax")}
= contact.fax
%br
%dt= t(:created)
%dd
%dd{class: changing_css_class(@version,"created_at")}
= l(contact.created_at, format: :short)
%dt= t(:updated)
%dd
%dd{class: changing_css_class(@version,"updated_at")}
= l(contact.updated_at, format: :short)
%dt= t(:registrar)
%dd
%dd{class: changing_css_class(@version,"registrar_id")}
- if contact.registrar.present?
= link_to(contact.registrar, admin_registrar_path(contact.registrar))
%dl.dl-horizontal
- if contact.org_name.present?
%dt= t(:org_name)
%dd= contact.org_name
%dd{class: changing_css_class(@version,"org_name")}= contact.org_name
- if contact.street.present?
%dt= t(:street)
%dd= contact.street.to_s.gsub("\n", '<br>').html_safe
%dd{class: changing_css_class(@version,"street")}= contact.street.to_s.gsub("\n", '<br>').html_safe
- if contact.city.present?
%dt= t(:city)
%dd= contact.city
%dd{class: changing_css_class(@version,"city")}= contact.city
- if contact.zip.present?
%dt= t(:zip)
%dd= contact.zip
%dd{class: changing_css_class(@version,"zip")}= contact.zip
- if contact.state.present?
%dt= t(:state)
%dd= contact.state
%dd{class: changing_css_class(@version,"state")}= contact.state
- if contact.country.present?
%dt= t(:country)
%dd= contact.country
%dd{class: changing_css_class(@version,"country_code")}= contact.country
%span{:style => "padding-right:10px; float: right;"}

View file

@ -29,15 +29,10 @@
.form-group
= label_tag t(:country)
= select_tag '[q][country_code_eq]', SortedCountry.all_options(params[:q][:country_code_eq]), { include_blank: true, placeholder: t(:choose), class: 'form-control selectize' }
.col-md-3
.form-group
= f.label t(:is_registrant)
%div
= f.check_box :registrant_domains_id_not_null
.col-md-3
.col-md-6
.form-group
= label_tag t(:contact_type)
= select_tag '[q][domain_contacts_type_in]', options_for_select([['admin', 'AdminDomainContact'], ['tech', 'TechDomainContact']], params[:q][:domain_contacts_type_in]), { multiple: true, placeholder: t(:choose), class: 'form-control js-combobox' }
= select_tag '[q][domain_contacts_type_in]', options_for_select([['admin', 'AdminDomainContact'], ['tech', 'TechDomainContact'], ['registrant', 'registrant']], params[:q][:domain_contacts_type_in]), { multiple: true, placeholder: t(:choose), class: 'form-control js-combobox' }
.row
.col-md-3
.form-group
@ -64,7 +59,13 @@
.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)
.col-md-3{style: 'padding-top: 25px;'}
.col-md-3
.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'
.row
.col-md-3{style: 'padding-top: 25px;float:right;'}
%button.btn.btn-primary
&nbsp;
%span.glyphicon.glyphicon-search

View file

@ -6,7 +6,7 @@
%dt= t(:id)
%dd= @contact.code
%dt= t(:password)
%dt= t(:authinfo_pw)
%dd
= text_field_tag :auth_info, @contact.auth_info, readonly: true, class: 'partially-hidden'

View file

@ -3,10 +3,11 @@
- if @version
- children = HashWithIndifferentAccess.new(@version.children)
- nameservers = Nameserver.where(id: children[:nameservers])
- tech_contacts = Contact.where(id: children[:tech_contacts])
- admin_contacts = Contact.where(id: children[:admin_contacts])
- registrant = Contact.where(id: children[:registrant])
- nameservers = Nameserver.all_versions_for(children[:nameservers], @version.created_at)
- dnskeys = Dnskey.all_versions_for(children[:dnskeys], @version.created_at)
- tech_contacts = Contact.all_versions_for(children[:tech_contacts], @version.created_at)
- admin_contacts = Contact.all_versions_for(children[:admin_contacts], @version.created_at)
- registrant = Contact.all_versions_for(children[:registrant], @version.created_at)
- event = @version.event
- creator = plain_username(@version.terminator)
@ -36,34 +37,44 @@
%br
%dt= t(:statuses)
%dd
%dd{class: changing_css_class(@version,"statuses")}
- if domain.statuses.present?
- domain.statuses.each do |s|
= s
%dt= t(:registrant)
%dd
%dd{class: changing_css_class(@version,"registrant_id")}
- registrant.each do |r|
- link = r.version_loader ? admin_contact_version_path(r.version_loader.try(:id)) : admin_contact_path(r.id)
= link_to link, target: "contact_#{r.id}" do
= r[:name]
= r[:phone]
= r[:email]
= r[:code]
%br
%dt= t(:admin_contacts)
%dd
- admin_contacts.each do |r|
- link = r.version_loader ? admin_contact_version_path(r.version_loader.try(:id)) : admin_contact_path(r.id)
= link_to link, target: "contact_#{r.id}" do
= r[:name]
= r[:phone]
= r[:email]
= r[:code]
%br
%dt= t(:tech_contacts)
%dd
- tech_contacts.each do |r|
- link = r.version_loader ? admin_contact_version_path(r.version_loader.try(:id)) : admin_contact_path(r.id)
= link_to link, target: "contact_#{r.id}" do
= r[:name]
= r[:phone]
= r[:email]
= r[:code]
%br
%dt= t(:nameservers)
%dd
- nameservers.each do |ns|
@ -71,9 +82,23 @@
= ns[:ipv4]
= ns[:ipv6]
%br
%dt= t(:dnskeys)
%dd
- dnskeys.each do |ns|
= ns[:flags]
= ns[:protocol]
= ns[:alg]
- if ns[:public_key].present?
\...#{ns[:public_key].to_s[-20,20]}
%br
%dt= t(:registrar)
%dd= domain.registrar.name
%div{:style => "margin: 20px 20px; clear:both;"}
%dd{class: changing_css_class(@version,"registrar_id")}
= link_to admin_registrar_path(domain.registrar), target: "registrar_#{domain.registrar.id}" do
= domain.registrar.name
%span{:style => "margin: 20px 20px; clear:both;"}
- if @version.previous
= link_to(t(:previous),
admin_domain_version_path(@version.previous.id),

View file

@ -12,7 +12,7 @@
%dt= t(:registrar)
%dd= link_to(@domain.registrar, admin_registrar_path(@domain.registrar))
%dt= t(:password)
%dt= t(:authinfo_pw)
%dd
= text_field_tag :password, @domain.auth_info, readonly: true, class: 'partially-hidden'

View file

@ -1,4 +1,4 @@
- statuses_link ||= false
-#- statuses_link ||= false
- version ||= false
- domain ||= false
- pending_user ||= false
@ -6,32 +6,42 @@
- if domain.present?
- if version # normal history
- children = HashWithIndifferentAccess.new(version.children)
- nameservers = Nameserver.where(id: children[:nameservers])
- tech_contacts = Contact.where(id: children[:tech_contacts])
- admin_contacts = Contact.where(id: children[:admin_contacts])
- registrant = Contact.where(id: children[:registrant])
- nameservers = Nameserver.all_versions_for(children[:nameservers], version.created_at)
- dnskeys = Dnskey.all_versions_for(children[:dnskeys], version.created_at)
- tech_contacts = Contact.all_versions_for(children[:tech_contacts], version.created_at)
- admin_contacts = Contact.all_versions_for(children[:admin_contacts], version.created_at)
- registrant = Contact.all_versions_for(children[:registrant], version.created_at)
- event = version.event
- creator = plain_username(version.terminator)
- else # pending history
- nameservers = domain.nameservers
- dnskeys = domain.dnskeys
- tech_contacts = domain.tech_contacts
- admin_contacts = domain.admin_contacts
- registrant = [domain.registrant]
- registrant = domain.registrant
- unless registrant
- ver = ContactVersion.where(item_id: domain.registrant_id).where(event: :destroy).last
- registrant = ver.reify
- registrant.version_loader = ver
- registrant = [registrant]
- creator = pending_user.try(:username)
- event = 'pending'
%td
%p.nowrap
= l(domain.updated_at, format: :shorts)
- if statuses_link
-#- if statuses_link
%br= link_to t(:edit_statuses), edit_admin_domain_path(params[:domain_id])
%p.text-right
= event
%br
= creator
- if version
%p.text-right
= link_to "Pure history", admin_domain_version_path(version)
%td
%td{class: changing_css_class(version,"statuses")}
%p
- if domain.statuses.present?
- domain.statuses.each do |s|
@ -46,7 +56,7 @@
%p
= link_to t(:pending_epp), '#', class: 'js-pending-toggle'
%td
%td{class: changing_css_class(version, "period", "period_unit", "valid_from", "valid_to")}
%p
= "#{domain.period}#{domain.period_unit}"
%br
@ -55,7 +65,9 @@
= "#{l(domain.valid_to, format: :date)}"
%td
- registrant.each do |r|
- Array(registrant).each do |r|
- link = r.version_loader ? admin_contact_version_path(r.version_loader.try(:id)) : admin_contact_path(r.id)
= link_to link, target: "contact_#{r.id}" do
%p
= r[:name]
= r[:phone]
@ -64,7 +76,9 @@
= r[:code]
%td
- admin_contacts.each do |ac|
- Array(admin_contacts).each do |ac|
- link = ac.version_loader ? admin_contact_version_path(ac.version_loader.try(:id)) : admin_contact_path(ac.id)
= link_to link, target: "contact_#{ac.id}" do
%p
= ac[:name]
= ac[:phone]
@ -73,7 +87,9 @@
= ac[:code]
%td
- tech_contacts.each do |tc|
- Array(tech_contacts).each do |tc|
- link = tc.version_loader ? admin_contact_version_path(tc.version_loader.try(:id)) : admin_contact_path(tc.id)
= link_to link, target: "contact_#{tc.id}" do
%p
= tc[:name]
= tc[:phone]
@ -83,14 +99,25 @@
%td
%p
- nameservers.each do |ns|
- Array(nameservers).each do |ns|
= ns[:hostname]
%br
= ns[:ipv4]
= ns[:ipv6]
= ns[:ipv4].presence
= ns[:ipv6].presence
%br
%td
- Array(dnskeys).each do |ns|
%p
= ns.flags
= ns.protocol
= ns.alg
- if ns.public_key.present?
\...#{ns.public_key.to_s[-20,20]}
%td{class: changing_css_class(version,"registrar_id")}
- if domain.registrar
%p
= link_to admin_registrar_path(domain.registrar), target: "registrar_#{domain.registrar.id}" do
= domain.registrar.name
- if domain.pending_json.present?

View file

@ -4,8 +4,8 @@
.row
.col-md-12
.table-responsive
%table.table-hover.table-bordered.table-condensed
.table-responsive{data: {doublescroll: true}}
%table.table.table-bordered.table-condensed
%thead
%tr
%th{class: 'col-xs-1'}= t(:timestap)
@ -15,10 +15,11 @@
%th{class: 'col-xs-2'}= t(:admin)
%th{class: 'col-xs-2'}= t(:tech)
%th{class: 'col-xs-2'}= t(:nameservers)
%th{class: 'col-xs-2'}= t(:dnskeys)
%th{class: 'col-xs-2'}= t(:registrar)
%tbody
- if @pending_domain.present?
-#- if @pending_domain.present?
%tr.small
= render 'admin/domains/partials/version',
domain: @pending_domain, pending_user: @pending_user, statuses_link: true

View file

@ -29,11 +29,11 @@
.col-md-3
.form-group
= f.label t(:created_after)
= f.search_field :created_at_gteq, class: 'form-control', placeholder: t(:created_after), autocomplete: 'off'
= f.search_field :created_at_gteq, value: params[:q][:created_at_gteq], class: 'form-control datepicker', placeholder: t(:created_after), autocomplete: 'off'
.col-md-3
.form-group
= f.label t(:created_before)
= f.search_field :created_at_lteq, class: 'form-control', placeholder: t(:created_before), autocomplete: 'off'
= f.search_field :created_at_lteq, value: params[:q][:created_at_lteq], class: 'form-control datepicker', placeholder: t(:created_before), autocomplete: 'off'
.col-md-3{style: 'padding-top: 25px;'}
%button.btn.btn-primary
&nbsp;

View file

@ -8,13 +8,13 @@
%thead
%tr
%th{class: 'col-xs-3'}
= sort_link(@q, 'invoice')
= sort_link(@q, :number)
%th{class: 'col-xs-3'}
= sort_link(@q, 'buyer')
= sort_link(@q, :buyer_name, "Buyer")
%th{class: 'col-xs-3'}
= sort_link(@q, 'due_date')
= sort_link(@q, :sort_due_date, "Due date")
%th{class: 'col-xs-3'}
= sort_link(@q, 'receipt_date')
= sort_link(@q, :sort_receipt_date, "Receipt date")
%tbody
- @invoices.each do |x|
%tr

View file

@ -28,7 +28,7 @@
%dt= t(:public_key)
%dd= @keyrelay.key_data_public_key
%dt= t(:password)
%dt= t(:authinfo_pw)
%dd= @keyrelay.auth_info_pw
%dt= t(:expiry_relative)

View file

@ -82,6 +82,11 @@
= f.label :code
.col-md-7
= f.text_field(:code, class: 'form-control', disabled: !f.object.new_record?)
.form-group
.col-md-4.control-label
= f.label :test_registrar
.col-md-7
= f.check_box :test_registrar, class: 'form-control'
%hr
.row

View file

@ -8,15 +8,21 @@
%table.table.table-hover.table-bordered.table-condensed
%thead
%tr
%th{class: 'col-xs-6'}
%th{class: 'col-xs-4'}
= sort_link(@q, 'name')
%th{class: 'col-xs-6'}
%th{class: 'col-xs-4'}
= sort_link(@q, 'reg_no', t(:reg_no))
%th{class: 'col-xs-4'}
= t(:credit_balance)
%th{class: 'col-xs-4'}
= t(:test_registrar)
%tbody
- @registrars.each do |x|
%tr
%td= link_to(x, [:admin, x])
%td= x.reg_no
%td= "#{x.balance}"
%td= "#{x.test_registrar}"
.row
.col-md-12
= paginate @registrars

View file

@ -2,6 +2,10 @@
= link_to(t(:edit), edit_admin_registrar_path(@registrar), class: 'btn btn-primary')
= link_to(t(:delete), admin_registrar_path(@registrar),
method: :delete, data: { confirm: t(:are_you_sure) }, class: 'btn btn-danger')
- content_for :page_name do
= @registrar.name
- if @registrar.test_registrar?
%span{style: "color: #c9302c;"} (test)
= render 'shared/title', name: @registrar.name
- if @registrar.errors.any?
@ -32,6 +36,9 @@
%dt= t(:id)
%dd= @registrar.code
%dt= t(:credit_balance)
%dd= @registrar.balance
.col-md-6
.panel.panel-default
.panel-heading

View file

@ -29,11 +29,11 @@
.col-md-3
.form-group
= f.label t(:created_after)
= f.search_field :created_at_gteq, class: 'form-control', placeholder: t(:created_after), autocomplete: 'off'
= f.search_field :created_at_gteq, value: params[:q][:created_at_gteq], class: 'form-control datepicker', placeholder: t(:created_after), autocomplete: 'off'
.col-md-3
.form-group
= f.label t(:created_before)
= f.search_field :created_at_lteq, class: 'form-control', placeholder: t(:created_before), autocomplete: 'off'
= f.search_field :created_at_lteq, value: params[:q][:created_at_lteq], class: 'form-control datepicker', placeholder: t(:created_before), autocomplete: 'off'
.col-md-3{style: 'padding-top: 25px;'}
%button.btn.btn-primary
&nbsp;

View file

@ -0,0 +1,22 @@
= form_for([:admin, @domain], html: {class: 'form-horizontal'}) do |f|
= render 'shared/full_errors', object: @domain
.row
.col-md-8
.panel.panel-default
.panel-heading.clearfix
.pull-left= t(:general)
.panel-body
.form-group
.col-md-4.control-label
= f.label :name
.col-md-7
= f.text_field(:name, class: 'form-control', disabled: !f.object.new_record?)
.form-group
.col-md-4.control-label
= f.label :password
.col-md-7
= f.text_field(:password, placeholder: t(:optional), class: 'form-control')
.row
.col-md-8.text-right
= button_tag(t(:save), class: 'btn btn-primary')

View file

@ -0,0 +1,3 @@
= render 'shared/title', name: t(:edit_pw)
= render 'form'

View file

@ -1,14 +1,72 @@
- content_for :actions do
= link_to('#', class: 'btn btn-default', "data-container": "body", "data-title": t('list_format_is_in_yaml'), "data-content": "domain.ee: authinfopw<br>seconddomain.ee:<br>thirddomain.ee: authinfo3<br><br>#{t('if_auth_info_is_left_empty_it_will_be_auto_generated')}<br>#{t('each_domain_name_must_end_with_colon_sign')}", "data-placement": "left", "data-toggle": "popover", "data-html" => "true") do
%span.glyphicon.glyphicon-info-sign{"aria-hidden" => "true"}
= link_to(t(:new), new_admin_reserved_domain_path, class: 'btn btn-primary')
= render 'shared/title', name: t(:reserved_domains)
= form_tag([:admin, :reserved_domains]) do |f|
.row
.col-md-12
= text_area_tag :reserved_domains, @reserved_domains, class: 'form-control', rows: 30
= search_form_for [:admin, @q], html: { style: 'margin-bottom: 0;', class: 'js-form', autocomplete: 'off' } do |f|
.row
.col-md-3
.form-group
= f.label :name
= f.search_field :name_matches, value: params[:q][:name_matches], class: 'form-control', placeholder: t(:name)
.col-md-3
.form-group
= f.label t(:created_at_from)
= f.search_field :created_at_gteq, value: params[:q][:created_at_gteq], class: 'form-control datepicker', placeholder: t(:created_at_from)
.col-md-3
.form-group
= f.label t(:created_at_until)
= f.search_field :created_at_lteq, value: params[:q][:created_at_lteq], class: 'form-control datepicker', placeholder: t(:created_at_until)
.row
.col-md-3
.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)
.col-md-3{style: 'padding-top: 25px;'}
%button.btn.btn-primary
&nbsp;
%span.glyphicon.glyphicon-search
&nbsp;
%button.btn.btn-default.js-reset-form
= t(:clear_fields)
%hr
.row
.col-md-12.text-right
%button.btn.btn-warning=t(:save)
.col-md-12
.table-responsive
%table.table.table-hover.table-bordered.table-condensed
%thead
%tr
%th{class: 'col-xs-2'}
= sort_link(@q, 'name')
%th{class: 'col-xs-2'}
= sort_link(@q, 'password')
%th{class: 'col-xs-2'}
= sort_link(@q, 'created_at', t(:created_at))
%th{class: 'col-xs-2'}
= sort_link(@q, 'updated_at', t(:updated_at))
%th{class: 'col-xs-2'}
= t(:actions)
%tbody
- @domains.each do |x|
%tr
%td= x.name
%td= x.password
%td= l(x.created_at, format: :short)
%td= l(x.updated_at, format: :short)
%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')
.row
.col-md-6
= paginate @domains
.col-md-6.text-right
.pagination
= t(:result_count, count: @domains.total_count)
:coffee
$(".js-reset-form").on "click", (e) ->
e.preventDefault();
window.location = "#{admin_reserved_domains_path}"

View file

@ -0,0 +1,3 @@
= render 'shared/title', name: t(:add_reserved_domain)
= render 'form'

View file

@ -36,6 +36,7 @@
= render 'setting_row', var: :days_to_renew_domain_before_expire
= render 'setting_row', var: :expire_warning_period
= render 'setting_row', var: :redemption_grace_period
= render 'setting_row', var: :expiration_reminder_mail
.panel.panel-default
.panel-heading.clearfix
@ -50,6 +51,7 @@
= render 'setting_row', var: :transfer_wait_time
= render 'setting_row', var: :ds_digest_type
= render 'setting_row', var: :client_side_status_editing_enabled
= render 'setting_row', var: :days_to_keep_business_registry_cache
= render 'setting_row', var: :api_ip_whitelist_enabled
= render 'setting_row', var: :registrar_ip_whitelist_enabled
= render 'setting_row', var: :request_confrimation_on_registrant_change_enabled
@ -67,9 +69,15 @@
%tbody
= render 'setting_row', var: :invoice_number_min
= render 'setting_row', var: :invoice_number_max
= render 'setting_row', var: :directo_monthly_number_min
= render 'setting_row', var: :directo_monthly_number_max
= render 'setting_row', var: :directo_monthly_number_last
= render 'setting_row', var: :days_to_keep_invoices_active
= render 'setting_row', var: :days_to_keep_overdue_invoices_active
= render 'setting_row', var: :minimum_deposit
= render 'setting_row', var: :directo_receipt_payment_term
= render 'setting_row', var: :directo_receipt_product_name
= render 'setting_row', var: :directo_sales_agent
= render 'setting_row', var: :registry_billing_email
= render 'setting_row', var: :registry_invoice_contact
= render 'setting_row', var: :registry_vat_no

View file

@ -46,15 +46,15 @@ xml.epp_head do
xml.tag!('contact:email', 'No access')
end
xml.tag!('contact:clID', @contact.registrar.try(:name))
if @contact.creator.try(:registrar).blank? && Rails.env.test?
xml.tag!('contact:crID', 'TEST-CREATOR')
else
xml.tag!('contact:crID', @contact.creator.try(:registrar))
end
xml.tag!('contact:clID', @contact.registrar.try(:code))
xml.tag!('contact:crID', @contact.cr_id)
xml.tag!('contact:crDate', @contact.created_at.try(:iso8601))
if @contact.updated_at != @contact.created_at
xml.tag!('contact:upID', @contact.updator.try(:registrar))
if @contact.updated_at > @contact.created_at
upID = @contact.updator.try(:registrar)
upID = upID.code if upID.present? # Did updator return a kind of User that has a registrar?
xml.tag!('contact:upID', upID) if upID.present? # optional upID
xml.tag!('contact:upDate', @contact.updated_at.try(:iso8601))
end
# xml.tag!('contact:trDate', '123') if false

View file

@ -36,19 +36,20 @@ xml.epp_head do
## TODO Find out what this domain:host is all about
xml.tag!('domain:clID', @domain.registrar_name)
xml.tag!('domain:crID', @domain.creator.try(:registrar)) if @domain.creator
xml.tag!('domain:clID', @domain.registrar.code)
xml.tag!('domain:crID', @domain.cr_id)
xml.tag!('domain:crDate', @domain.created_at.try(:iso8601))
xml.tag!('domain:upDate', @domain.updated_at.try(:iso8601)) if @domain.updated_at != @domain.created_at
if @domain.updated_at > @domain.created_at
upID = @domain.updator.try(:registrar)
upID = upID.code if upID.present? # Did updator return a kind of User that has a registrar?
xml.tag!('domain:upID', upID) if upID.present? # optional upID
xml.tag!('domain:upDate', @domain.updated_at.try(:iso8601))
end
xml.tag!('domain:exDate', @domain.valid_to.try(:iso8601))
# TODO Make domain stampable
#xml.tag!('domain:upID', @domain.updated_by)
# TODO Make domain transferrable
#xml.tag!('domain:trDate', @domain.transferred_at) if @domain.transferred_at

View file

@ -9,15 +9,11 @@ xml.epp_head do
xml.msg @message.body
end
if @message.attached_obj_type == 'DomainTransfer'
xml.resData do
case @message.attached_obj_type
when 'DomainTransfer'
xml << render('epp/domains/partials/transfer', builder: xml, dt: @object)
when 'DomainVersion'
xml << render('epp/domains/partials/delete_complete', builder: xml, bye_bye: @object)
end
end if @object
end
render('epp/shared/trID', builder: xml)
end
end

View file

@ -0,0 +1,8 @@
Estonia .ee Top Level Domain WHOIS server
Domain:
name: <%= @json['name'] %>
status: <%= @json['status'] %>
Estonia .ee Top Level Domain WHOIS server
More information at http://internet.ee

View file

@ -55,7 +55,7 @@
%li= link_to t(:pricelists), admin_pricelists_path
%li= link_to t(:bank_statements), admin_bank_statements_path
%li= link_to t(:invoices), admin_invoices_path
%li= link_to t(:account_activities), admin_account_activities_path
%li= link_to t(:account_activities), admin_account_activities_path(created_after: 'today')
%li.divider
%li.dropdown-header= t(:archive)
%li= link_to t(:domains_history), admin_domain_versions_path
@ -68,8 +68,8 @@
%li= link_to t(:reserved_domains), admin_reserved_domains_path
%li= link_to t(:mail_templates), admin_mail_templates_path
-# %li= link_to t(:domains_history), admin_domain_versions_path
%li= link_to t(:epp_logs), admin_epp_logs_path
%li= link_to t(:repp_logs), admin_repp_logs_path
%li= link_to t(:epp_logs), admin_epp_logs_path(created_after: 'today')
%li= link_to t(:repp_logs), admin_repp_logs_path(created_after: 'today')
%li= link_to t(:que), '/admin/que'
- if signed_in?

View file

@ -1,10 +1,10 @@
Tere <%= @contact.name %>
<br><br>
Kontakti <%= @contact.name %> eposti aadress on muudetud<br>
Kontakti <%= @contact.name %> e-posti aadress on muudetud<br>
endine aadress: <%= @old_email %><br>
uus aadress: <%= @contact.email %>
<br><br>
Eposti aadressile saadetakse domeenidega seotud infot seal hulgas kinnitustaotluseid omaniku vahetuse ja domeeni kustutamise korral. Palun veenduge, et muudatus on korrektne ning probleemide korral pöörduga oma registripidaja poole. Teie registripidaja on <%= @contact.registrar.name %>
E-posti aadressile saadetakse domeeni toimingutega seotud infot, sealhulgas kinnitustaotlused omanikuvahetuse ja domeeni kustutamise korral. Palun veenduge, et muudatus on korrektne ning probleemide korral pöörduge oma registripidaja <%= @contact.registrar.name %> poole.
<br><br>
<% if @contact.related_domain_descriptions.present? %>
Muudatusega seotud domeenid:<br>
@ -16,14 +16,14 @@ Muudatusega seotud domeenid:<br>
Kontaktandmed:<br>
Nimi: <%= @contact.name %><br>
Isikukood: <%= @contact.ident %><br>
Epost: <%= @contact.email %><br>
E-post: <%= @contact.email %><br>
Tel: <%= @contact.phone %><br>
Tänav: <%= @contact.street %><br>
Linn: <%= @contact.city %><br>
Riik: <%= @contact.country %>
<br><br>
Lugupidamisega<br>
Eesti Interneti SA
Eesti Interneti Sihtasutus
<br><br>
<hr>
<br><br>
@ -52,4 +52,4 @@ City: <%= @contact.city %><br>
Country: <%= @contact.country %>
<br><br>
Best Regards,<br>
Eesti Interneti SA
Estonian Internet Foundation

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