Merge branch 'master' into alpha

This commit is contained in:
Priit Tark 2015-07-15 10:18:07 +03:00
commit 231c944d3a
84 changed files with 3729 additions and 1113 deletions

View file

@ -5,6 +5,7 @@ AllCops:
- 'Guardfile'
# stuff generated by AR and rails
- 'db/schema.rb'
- 'db/schema-read-only.rb'
- 'db/whois_schema.rb'
- 'db/api_log_schema.rb'
- 'db/migrate/*'
@ -115,3 +116,7 @@ Style/FirstParameterIndentation:
# old school regex // works fine
Style/RegexpLiteral:
Enabled: false
# annoying to maintain, small thing, no real problem
Style/SpaceInsideHashLiteralBraces:
Enabled: false

View file

@ -17,7 +17,6 @@ before_script:
- cp config/database-travis.yml config/database.yml
- RAILS_ENV=test bundle exec rake db:all:drop
- RAILS_ENV=test bundle exec rake db:all:setup
- RAILS_ENV=test bundle exec rake zonefile:replace_procedure
script:
- RAILS_ENV=test bundle exec rake
cache: bundler

View file

@ -1,3 +1,12 @@
14.07.2015
* Updated que init script doc example, now status and stop works faster
* Updated registry server cronjob with mina cron:setup
07.07.2015
* Before applyling 20150707104937_refactor_reserved_domains.rb migration, enable hstore extension in db
01.07.2015
* Added que init script example at doc/que directory, please setup que accornding to doc/que/README.md

View file

@ -13,7 +13,7 @@ gem 'iso8601', '~> 0.8.2' # for dates and times
gem 'hashie-forbidden_attributes', '~> 0.1.1'
# load env
gem 'figaro', '~> 1.1.0'
gem 'figaro', '~> 1.1.1'
# model related
gem 'pg', '~> 0.18.0'
@ -103,9 +103,10 @@ group :development do
# dev tools
gem 'spring', '~> 1.3.6'
gem 'spring-commands-rspec', '~> 1.0.4'
gem 'spring-watcher-listen', # otherwise spring polls the filesystem on every 0.2 seconds
github: 'jonleighton/spring-watcher-listen',
ref: '7f6003e14f8f9ca178a5194f210c07f54cfb67ec'
# emits errors, needs more investigation
# gem 'spring-watcher-listen', # otherwise spring polls the filesystem on every 0.2 seconds
# github: 'jonleighton/spring-watcher-listen',
# ref: '7f6003e14f8f9ca178a5194f210c07f54cfb67ec'
gem 'guard', '~> 2.12.6' # run tests automatically
gem 'guard-rspec', '~> 4.5.2'
gem 'guard-rails', '~> 0.7.1' # run EPP server automatically

View file

@ -24,15 +24,6 @@ GIT
hpricot
libxml-ruby
GIT
remote: https://github.com/jonleighton/spring-watcher-listen.git
revision: 7f6003e14f8f9ca178a5194f210c07f54cfb67ec
ref: 7f6003e14f8f9ca178a5194f210c07f54cfb67ec
specs:
spring-watcher-listen (1.0.0)
listen (~> 2.7)
spring (~> 1.2)
GIT
remote: https://github.com/rubysec/bundler-audit.git
revision: f89ef7fae1090bbad825ea76812d56d72b417055
@ -576,7 +567,7 @@ DEPENDENCIES
epp-xml (~> 1.0.3)
fabrication (~> 2.13.2)
faker (~> 1.4.3)
figaro (~> 1.1.0)
figaro (~> 1.1.1)
grape (~> 0.12.0)
guard (~> 2.12.6)
guard-rails (~> 0.7.1)
@ -625,7 +616,6 @@ DEPENDENCIES
simpleidn (~> 0.0.5)
spring (~> 1.3.6)
spring-commands-rspec (~> 1.0.4)
spring-watcher-listen!
therubyracer (~> 0.12.2)
traceroute (~> 0.5.0)
turbolinks (~> 2.5.3)

View file

@ -13,10 +13,11 @@ class Admin::BlockedDomainsController < AdminController
if bd.update(names: names)
flash[:notice] = I18n.t('record_updated')
else
flash.now[:alert] = I18n.t('failed_to_update_record')
end
redirect_to :back
else
@blocked_domains = params[:blocked_domains]
flash.now[:alert] = I18n.t('failed_to_update_record')
render :index
end
end
end

View file

@ -1,6 +1,8 @@
class Admin::InvoicesController < AdminController
load_and_authorize_resource
before_action :set_invoice, only: [:forward, :download_pdf]
def new
@deposit = Deposit.new
end
@ -39,9 +41,33 @@ class Admin::InvoicesController < AdminController
end
end
def forward
@invoice.billing_email = @invoice.buyer.billing_email
return unless request.post?
@invoice.billing_email = params[:invoice][:billing_email]
if @invoice.forward(render_to_string('registrar/invoices/pdf', layout: false))
flash[:notice] = t(:invoice_forwared)
redirect_to([:admin, @invoice])
else
flash.now[:alert] = t(:failed_to_forward_invoice)
end
end
def download_pdf
pdf = @invoice.pdf(render_to_string('registrar/invoices/pdf', layout: false))
send_data pdf, filename: @invoice.pdf_name
end
private
def deposit_params
params.require(:deposit).permit(:amount, :description, :registrar_id)
end
def set_invoice
@invoice = Invoice.find(params[:invoice_id])
end
end

View file

@ -32,6 +32,11 @@ class Admin::PricelistsController < AdminController
end
end
def destroy
@pricelist.destroy
redirect_to admin_pricelists_url
end
private
def set_pricelist

View file

@ -0,0 +1,30 @@
class Admin::ReservedDomainsController < AdminController
load_and_authorize_resource
def index
rd = ReservedDomain.first_or_initialize
@reserved_domains = rd.names.to_yaml
end
def create
@reserved_domains = params[:reserved_domains]
begin
names = YAML.load(params[:reserved_domains])
rescue
flash.now[:alert] = I18n.t('invalid_yaml')
logger.warn 'Invalid YAML'
render :index and return
end
rd = ReservedDomain.first_or_create
if rd.update(names: names)
flash[:notice] = I18n.t('record_updated')
redirect_to :back
else
flash.now[:alert] = I18n.t('failed_to_update_record')
render :index
end
end
end

View file

@ -56,7 +56,8 @@ class Admin::SettingsController < AdminController
:days_to_keep_overdue_invoices_active,
:days_to_renew_domain_before_expire,
:expire_warning_period,
:redemption_grace_period
:redemption_grace_period,
:expire_pending_confirmation
]
floats = [:registry_vat_prc]

View file

@ -18,16 +18,34 @@ class Epp::DomainsController < EppController
render_epp_response '/epp/domains/info'
end
# rubocop: disable Metrics/PerceivedComplexity
# rubocop: disable Metrics/CyclomaticComplexity
def create
authorize! :create, Epp::Domain
@domain = Epp::Domain.new_from_epp(params[:parsed_frame], current_user)
handle_errors(@domain) and return if @domain.errors.any?
@domain.valid?
handle_errors(@domain) and return if @domain.errors.any?
handle_errors and return unless balance_ok?('create')
ActiveRecord::Base.transaction do
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,
description: "#{I18n.t('create')} #{@domain.name}",
activity_type: AccountActivity::CREATE,
log_pricelist_id: @domain_pricelist.id
})
if @domain.errors.any? || !@domain.save
handle_errors(@domain)
else
render_epp_response '/epp/domains/create'
else
handle_errors(@domain)
end
end
end
# rubocop: enable Metrics/PerceivedComplexity
# rubocop: enable Metrics/CyclomaticComplexity
def update
authorize! :update, @domain, @password
@ -76,13 +94,33 @@ class Epp::DomainsController < EppController
def renew
authorize! :renew, @domain
handle_errors(@domain) and return unless @domain.renew(
period = params[:parsed_frame].css('period').text
period_unit = params[:parsed_frame].css('period').first['unit']
ActiveRecord::Base.transaction do
success = @domain.renew(
params[:parsed_frame].css('curExpDate').text,
params[:parsed_frame].css('period').text,
params[:parsed_frame].css('period').first['unit']
period, period_unit
)
if success
unless balance_ok?('renew', period, period_unit)
handle_errors
fail ActiveRecord::Rollback
end
current_user.registrar.debit!({
sum: @domain_pricelist.price.amount,
description: "#{I18n.t('renew')} #{@domain.name}",
activity_type: AccountActivity::RENEW,
log_pricelist_id: @domain_pricelist.id
})
render_epp_response '/epp/domains/renew'
else
handle_errors(@domain)
end
end
end
def transfer
@ -154,7 +192,7 @@ class Epp::DomainsController < EppController
requires 'name'
@prefix = nil
requires_attribute 'transfer', 'op', values: %(approve, query, reject)
requires_attribute 'transfer', 'op', values: %(approve, query, reject, request)
end
def find_domain
@ -185,4 +223,17 @@ class Epp::DomainsController < EppController
msg: "#{I18n.t(:client_side_status_editing_error)}: status [status]"
}
end
def balance_ok?(operation, period = nil, unit = nil)
@domain_pricelist = @domain.pricelist(operation, period.try(:to_i), unit)
if current_user.registrar.balance < @domain_pricelist.price.amount
epp_errors << {
code: '2104',
msg: I18n.t('billing_failure_credit_balance_low')
}
return false
end
true
end
end

View file

@ -13,6 +13,15 @@ class Epp::SessionsController < EppController
success = true
@api_user = ApiUser.find_by(login_params)
if request.ip == ENV['webclient_ip'] && !Rails.env.test? && !Rails.env.development?
client_md5 = Certificate.parse_md_from_string(request.env['HTTP_SSL_CLIENT_CERT'])
server_md5 = Certificate.parse_md_from_string(File.read(ENV['cert_path']))
if client_md5 != server_md5
@msg = 'Authentication error; server closing connection (certificate is not valid)'
success = false
end
end
if request.ip != ENV['webclient_ip'] && @api_user
unless @api_user.api_pki_ok?(request.env['HTTP_SSL_CLIENT_CERT'], request.env['HTTP_SSL_CLIENT_S_DN_CN'])
@msg = 'Authentication error; server closing connection (certificate is not valid)'

View file

@ -10,15 +10,29 @@ class EppController < ApplicationController
before_action :update_epp_session
helper_method :current_user
rescue_from CanCan::AccessDenied do |_exception|
rescue_from StandardError do |e|
@errors ||= []
if e.class == CanCan::AccessDenied
if @errors.blank?
@errors = [{
msg: t('errors.messages.epp_authorization_error'),
code: '2201'
}]
end
else
if @errors.blank?
@errors = [{
msg: 'Internal error.',
code: '2400'
}]
end
logger.error e.message
logger.error e.backtrace.join("\n")
# TODO: NOITFY AIRBRAKE / ERRBIT HERE
end
render_epp_response '/epp/error'
end
@ -124,7 +138,7 @@ class EppController < ApplicationController
# validate legal document's type here because it may be in most of the requests
@prefix = nil
if element_count('extdata > legalDocument') > 0
requires_attribute('extdata > legalDocument', 'type', values: LegalDocument::TYPES)
requires_attribute('extdata > legalDocument', 'type', values: LegalDocument::TYPES, policy: true)
end
handle_errors and return if epp_errors.any?
@ -174,12 +188,27 @@ class EppController < ApplicationController
attribute = element[attribute_selector]
return if attribute && options[:values].include?(attribute)
unless attribute
epp_errors << {
code: '2003',
msg: I18n.t('errors.messages.required_parameter_missing', key: attribute_selector)
}
return
end
return if options[:values].include?(attribute)
if options[:policy]
epp_errors << {
code: '2306',
msg: I18n.t('attribute_is_invalid', attribute: attribute_selector)
}
else
epp_errors << {
code: '2004',
msg: I18n.t('parameter_value_range_error', key: attribute_selector)
}
end
end
def optional_attribute(element_selector, attribute_selector, options)

View file

@ -1,10 +1,28 @@
class Registrar::AccountActivitiesController < RegistrarController
load_and_authorize_resource
def index
def index # rubocop: disable Metrics/AbcSize
params[:q] ||= {}
account = current_user.registrar.cash_account
ca_cache = params[:q][:created_at_lteq]
begin
end_time = params[:q][:created_at_lteq].try(:to_date)
params[:q][:created_at_lteq] = end_time.try(:end_of_day)
rescue
logger.warn('Invalid date')
end
@q = account.activities.includes(:invoice).search(params[:q])
@q.sorts = 'id desc' if @q.sorts.empty?
@account_activities = @q.result.page(params[:page])
respond_to do |format|
format.html { @account_activities = @q.result.page(params[:page]) }
format.csv do
send_data @q.result.to_csv, filename: "account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv"
end
end
params[:q][:created_at_lteq] = ca_cache
end
end

View file

@ -3,7 +3,7 @@ class DomainMailer < ApplicationMailer
@domain = domain
return if Rails.env.production? ? false : !TEST_EMAILS.include?(@domain.registrant_email)
# turn on delivery on specific request only, thus rake tasks does not deliver anything
# turn on delivery on specific EPP request only, thus rake tasks does not deliver anything
return if @domain.deliver_emails != true
if @domain.registrant_verification_token.blank?
@ -25,11 +25,22 @@ class DomainMailer < ApplicationMailer
subject: "#{I18n.t(:domain_registrant_pending_updated_subject, name: @domain.name)} [#{@domain.name}]")
end
def registrant_updated(domain)
@domain = domain
return if Rails.env.production? ? false : !TEST_EMAILS.include?(@domain.registrant_email)
# turn on delivery on specific EPP request only, thus rake tasks does not deliver anything
return if @domain.deliver_emails != true
mail(to: @domain.registrant_email,
subject: "#{I18n.t(:domain_registrant_updated, name: @domain.name)} [#{@domain.name}]")
end
def pending_deleted(domain)
@domain = domain
return if Rails.env.production? ? false : !TEST_EMAILS.include?(@domain.registrant_email)
# turn on delivery on specific request only, thus rake tasks does not deliver anything
# turn on delivery on specific EPP request only, thus rake tasks does not deliver anything
return if @domain.deliver_emails != true
if @domain.registrant_verification_token.blank?

View file

@ -107,6 +107,7 @@ class Ability
customer_service
can :manage, Setting
can :manage, BlockedDomain
can :manage, ReservedDomain
can :manage, ZonefileSetting
can :manage, DomainVersion
can :manage, Pricelist

View file

@ -1,13 +1,37 @@
require 'csv'
class AccountActivity < ActiveRecord::Base
include Versions
belongs_to :account
belongs_to :bank_transaction
belongs_to :invoice
CREATE = 'create'
RENEW = 'renew'
ADD_CREDIT = 'add_credit'
after_create :update_balance
def update_balance
account.balance += sum
account.save
end
class << self
def types_for_select
[CREATE, RENEW, ADD_CREDIT].map { |x| [I18n.t(x), x] }
end
def to_csv
attributes = %w(description activity_type created_at sum)
CSV.generate(headers: true) do |csv|
csv << %w(description activity_type receipt_date sum)
all.each do |x| # rubocop:disable Rails/FindEach
csv << attributes.map { |attr| x.send(attr) }
end
end
end
end
end

View file

@ -3,7 +3,9 @@ class BankTransaction < ActiveRecord::Base
belongs_to :bank_statement
has_one :account_activity
scope :unbinded, -> { where('id NOT IN (SELECT bank_transaction_id FROM account_activities)') }
scope :unbinded, lambda {
where('id NOT IN (SELECT bank_transaction_id FROM account_activities where bank_transaction_id IS NOT NULL)')
}
def binded?
account_activity.present?
@ -77,7 +79,8 @@ class BankTransaction < ActiveRecord::Base
invoice: invoice,
sum: invoice.sum_without_vat,
currency: currency,
description: description
description: description,
activity_type: AccountActivity::ADD_CREDIT
)
end
end

View file

@ -200,5 +200,14 @@ class Certificate < ActiveRecord::Base
_out, _err, _st = Open3.capture3("sudo /etc/init.d/apache2 reload")
STDOUT << "#{Time.zone.now.utc} - Apache reloaded\n"
end
def parse_md_from_string(crt)
return nil if crt.blank?
crt = crt.split(' ').join("\n")
crt.gsub!("-----BEGIN\nCERTIFICATE-----\n", "-----BEGIN CERTIFICATE-----\n")
crt.gsub!("\n-----END\nCERTIFICATE-----", "\n-----END CERTIFICATE-----")
cert = OpenSSL::X509::Certificate.new(crt)
OpenSSL::Digest::MD5.new(cert.to_der).to_s
end
end
end

View file

@ -79,7 +79,8 @@ module Depp
end
def transfer(params)
op = params[:query] ? 'query' : nil
op = params[:request] ? 'request' : nil
op = params[:query] ? 'query' : op
op = params[:approve] ? 'approve' : op
op = params[:reject] ? 'reject' : op
@ -182,16 +183,18 @@ module Depp
# rubocop:enable Metrics/AbcSize
def construct_custom_params_hash(domain_params)
custom_params = {}
custom_params = { _anonymus: [] }
if domain_params[:legal_document].present?
type = domain_params[:legal_document].original_filename.split('.').last.downcase
custom_params = {
_anonymus: [
custom_params[:_anonymus] << {
legalDocument: { value: Base64.encode64(domain_params[:legal_document].read), attrs: { type: type } }
]
}
end
if domain_params[:reserved_pw].present?
custom_params[:_anonymus] << { reserved: { pw: { value: domain_params[:reserved_pw] } } }
end
custom_params
end

View file

@ -61,6 +61,7 @@ class Domain < ActiveRecord::Base
before_create :generate_auth_info
before_create :set_validity_dates
before_create -> { self.reserved = in_reserved_list?; nil }
before_update :manage_statuses
def manage_statuses
return unless registrant_id_changed?
@ -78,12 +79,32 @@ class Domain < ActiveRecord::Base
after_initialize -> { self.statuses = [] if statuses.nil? }
after_create :update_reserved_domains
def update_reserved_domains
return unless in_reserved_list?
rd = ReservedDomain.first
rd.names[name] = SecureRandom.hex
rd.save
end
validates :name_dirty, domain_name: true, uniqueness: true
validates :puny_label, length: { maximum: 63 }
validates :period, numericality: { only_integer: true }
validates :registrant, :registrar, presence: true
validate :validate_period
validate :validate_reservation
def validate_reservation
return if persisted? || !in_reserved_list?
if reserved_pw.blank?
errors.add(:base, :required_parameter_missing_reserved)
return false
end
return if ReservedDomain.pw_for(name) == reserved_pw
errors.add(:base, :invalid_auth_information_reserved)
end
validates :nameservers, object_count: {
min: -> { Setting.ns_min_count },
@ -134,7 +155,7 @@ class Domain < ActiveRecord::Base
end
attr_accessor :registrant_typeahead, :update_me, :deliver_emails,
:epp_pending_update, :epp_pending_delete
:epp_pending_update, :epp_pending_delete, :reserved_pw
def subordinate_nameservers
nameservers.select { |x| x.hostname.end_with?(name) }
@ -146,8 +167,8 @@ class Domain < ActiveRecord::Base
class << self
def convert_period_to_time(period, unit)
return period.to_i.days if unit == 'd'
return period.to_i.months if unit == 'm'
return (period.to_i / 365).years if unit == 'd'
return (period.to_i / 12).years if unit == 'm'
return period.to_i.years if unit == 'y'
end
@ -162,16 +183,34 @@ class Domain < ActiveRecord::Base
)
end
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?
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
domain.clean_pendings!
end
STDOUT << "#{Time.zone.now.utc} - Successfully cancelled #{count} domain pendings\n" unless Rails.env.test?
count
end
def start_expire_period
STDOUT << "#{Time.zone.now.utc} - Expiring domains\n" unless Rails.env.test?
d = Domain.where('valid_to <= ?', Time.zone.now)
d.each do |x|
next unless x.expirable?
x.statuses << DomainStatus::EXPIRED
# TODO: This should be managed by automatic_statuses
x.statuses.delete(DomainStatus::OK)
x.save(validate: false)
domains = Domain.where('valid_to <= ?', Time.zone.now)
domains.each do |domain|
next unless domain.expirable?
domain.set_expired!
end
STDOUT << "#{Time.zone.now.utc} - Successfully expired #{d.count} domains\n" unless Rails.env.test?
@ -247,6 +286,10 @@ class Domain < ActiveRecord::Base
@registrant_typeahead || registrant.try(:name) || nil
end
def in_reserved_list?
ReservedDomain.pw_for(name).present?
end
def pending_transfer
domain_transfers.find_by(status: DomainTransfer::PENDING)
end
@ -372,6 +415,25 @@ class Domain < ActiveRecord::Base
DomainMailer.pending_deleted(self).deliver_now
end
def pricelist(operation, period_i = nil, unit = nil)
period_i ||= period
unit ||= period_unit
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)
end
### VALIDATIONS ###
def validate_nameserver_ips
@ -473,6 +535,19 @@ class Domain < ActiveRecord::Base
save(validate: false)
end
def set_expired
# 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
statuses << DomainStatus::EXPIRED
end
def set_expired!
set_expired
save(validate: false)
end
def manage_automatic_statuses
# domain_statuses.create(value: DomainStatus::DELETE_CANDIDATE) if delete_candidateable?
if statuses.empty? && valid?

View file

@ -71,6 +71,7 @@ class DomainStatus < ActiveRecord::Base
FORCE_DELETE = 'forceDelete'
DELETE_CANDIDATE = 'deleteCandidate'
EXPIRED = 'expired'
RESERVED = 'reserved'
STATUSES = [
CLIENT_DELETE_PROHIBITED, SERVER_DELETE_PROHIBITED, CLIENT_HOLD, SERVER_HOLD,

View file

@ -25,7 +25,8 @@ class Epp::Domain < Domain
],
'2003' => [ # Required parameter missing
[:registrant, :blank],
[:registrar, :blank]
[:registrar, :blank],
[:base, :required_parameter_missing_reserved]
],
'2004' => [ # Parameter value range error
[:nameservers, :out_of_range,
@ -60,6 +61,9 @@ class Epp::Domain < Domain
'2201' => [ # Authorisation error
[:auth_info, :wrong_pw]
],
'2202' => [
[:base, :invalid_auth_information_reserved]
],
'2302' => [ # Object exists
[:name_dirty, :taken, { value: { obj: 'name', val: name_dirty } }],
[:name_dirty, :reserved, { value: { obj: 'name', val: name_dirty } }],
@ -112,6 +116,8 @@ class Epp::Domain < Domain
at[:period_unit] = Epp::Domain.parse_period_unit_from_frame(frame) || 'y'
at[:reserved_pw] = frame.css('reserved > pw').text
# at[:statuses] = domain_statuses_attrs(frame, action)
# binding.pry
at[:nameservers_attributes] = nameservers_attrs(frame, action)
@ -392,7 +398,10 @@ class Epp::Domain < Domain
frame = Nokogiri::XML(pending_json['frame'])
statuses.delete(DomainStatus::PENDING_UPDATE)
clean_pendings! if update(frame, user, false)
return unless update(frame, user, false)
clean_pendings!
self.deliver_emails = true # turn on email delivery for epp
DomainMailer.registrant_updated(self).deliver_now
end
def apply_pending_delete!
@ -423,7 +432,7 @@ class Epp::Domain < Domain
manage_automatic_statuses
true # aka 1001 pending_delete
else
destroy
set_expired!
end
end
@ -455,6 +464,8 @@ class Epp::Domain < Domain
def transfer(frame, action, current_user)
case action
when 'query'
return domain_transfers.last if domain_transfers.any?
when 'request'
return pending_transfer if pending_transfer
return query_transfer(frame, current_user)
when 'approve'
@ -462,7 +473,7 @@ class Epp::Domain < Domain
when 'reject'
return reject_transfer(frame, current_user) if pending_transfer
end
add_epp_error('2303', nil, nil, I18n.t('pending_transfer_was_not_found'))
add_epp_error('2303', nil, nil, I18n.t('no_transfers_found'))
end
# TODO: Eager load problems here. Investigate how it's possible not to query contact again
@ -742,7 +753,7 @@ class Epp::Domain < Domain
next
end
unless DomainNameValidator.validate_reservation(x)
if ReservedDomain.pw_for(x).present?
res << { name: x, avail: 0, reason: I18n.t('errors.messages.epp_domain_reserved') }
next
end

View file

@ -7,7 +7,9 @@ class Invoice < ActiveRecord::Base
accepts_nested_attributes_for :invoice_items
scope :unbinded, -> { where('id NOT IN (SELECT invoice_id FROM account_activities)') }
scope :unbinded, lambda {
where('id NOT IN (SELECT invoice_id FROM account_activities where invoice_id IS NOT NULL)')
}
attr_accessor :billing_email
validates :billing_email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }, allow_blank: true
@ -36,7 +38,7 @@ class Invoice < ActiveRecord::Base
class << self
def cancel_overdue_invoices
logger.info "#{Time.zone.now.utc} - Cancelling overdue invoices\n"
STDOUT << "#{Time.zone.now.utc} - Cancelling overdue invoices\n" unless Rails.env.test?
cr_at = Time.zone.now - Setting.days_to_keep_overdue_invoices_active.days
invoices = Invoice.unbinded.where(
@ -45,7 +47,7 @@ class Invoice < ActiveRecord::Base
count = invoices.update_all(cancelled_at: Time.zone.now)
logger.info "#{Time.zone.now.utc} - Successfully cancelled #{count} overdue invoices\n"
STDOUT << "#{Time.zone.now.utc} - Successfully cancelled #{count} overdue invoices\n" unless Rails.env.test?
end
end

View file

@ -1,3 +0,0 @@
class Pending < ActiveRecord::Base
belongs_to :domain
end

View file

@ -1,6 +1,8 @@
class Pricelist < ActiveRecord::Base
include Versions # version/pricelist_version.rb
scope :valid, -> { where("valid_from <= ? AND valid_to >= ? OR valid_to IS NULL", Time.zone.now, Time.zone.now) }
monetize :price_cents
validates :price_cents, :price_currency, :price,
@ -13,10 +15,18 @@ class Pricelist < ActiveRecord::Base
after_initialize :init_values
def init_values
return unless new_record?
self.valid_from = Time.zone.now.beginning_of_year
self.valid_from = Time.zone.now.beginning_of_year unless valid_from
end
def name
"#{operation_category} #{category}"
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
end
end
end

View file

@ -12,6 +12,8 @@ class Registrar < ActiveRecord::Base
has_many :priv_contacts, -> { privs }, class_name: 'Contact'
has_many :white_ips, dependent: :destroy
delegate :balance, to: :cash_account
validates :name, :reg_no, :country_code, :email, :code, presence: true
validates :name, :reg_no, :reference_no, :code, uniqueness: true
validate :forbidden_codes
@ -121,6 +123,17 @@ class Registrar < ActiveRecord::Base
accounts.find_by(account_type: Account::CASH)
end
def debit!(args)
args[:sum] *= -1
args[:currency] = 'EUR'
cash_account.account_activities.create!(args)
end
def credit!(args)
args[:currency] = 'EUR'
cash_account.account_activities.create!(args)
end
def domain_transfers
at = DomainTransfer.arel_table
DomainTransfer.where(

View file

@ -1,3 +1,9 @@
class ReservedDomain < ActiveRecord::Base
include Versions # version/reserved_domain_version.rb
class << self
def pw_for(domain_name)
select("names -> '#{domain_name}' AS pw").first.try(:pw)
end
end
end

View file

@ -1,17 +1,11 @@
class DomainNameValidator < ActiveModel::EachValidator
# rubocop: disable Metrics/PerceivedComplexity
# rubocop: disable Metrics/CyclomaticComplexity
def validate_each(record, attribute, value)
if !self.class.validate_format(value)
record.errors[attribute] << (options[:message] || record.errors.generate_message(attribute, :invalid))
elsif !self.class.validate_blocked(value)
record.errors.add(attribute, (options[:message] || record.errors.generate_message(attribute, :blocked)))
elsif !self.class.validate_reservation(value)
record.errors.add(attribute, (options[:message] || record.errors.generate_message(attribute, :reserved)))
end
end
# rubocop: enable Metrics/PerceivedComplexity
# rubocop: enable Metrics/CyclomaticComplexity
class << self
def validate_format(value)
@ -41,10 +35,5 @@ class DomainNameValidator < ActiveModel::EachValidator
return true unless value
BlockedDomain.where("names @> ?::varchar[]", "{#{value}}").count == 0
end
def validate_reservation(value)
return true unless value
!ReservedDomain.exists?(name: value.mb_chars.downcase.strip)
end
end
end

View file

@ -1,4 +1,4 @@
= form_for([:admin, @admin_user], html: { class: 'form-horizontal' }) do |f|
= form_for([:admin, @admin_user], html: { class: 'form-horizontal', autocomplete: 'off' }) do |f|
= render 'shared/full_errors', object: @admin_user
.row
@ -14,12 +14,12 @@
- not_required = @admin_user.new_record? ? '' : 'not-required'
= f.label :password, class: not_required
.col-md-8
= f.password_field(:password, class: 'form-control')
= f.text_field(:password, class: 'form-control')
.form-group
.col-md-4.control-label
= f.label :password_confirmation, class: not_required
.col-md-8
= f.password_field(:password_confirmation, class: 'form-control')
= f.text_field(:password_confirmation, class: 'form-control')
%hr
.form-group
@ -48,7 +48,7 @@
%hr
.row
.col-md-8.text-right
= button_tag(t(:save), class: 'btn btn-primary')
= button_tag(t(:save), class: 'btn btn-warning')
:coffee
$("#admin_user_password").removeAttr('required')

View file

@ -0,0 +1,15 @@
- content_for :actions do
= link_to(t(:back_to_invoice), admin_invoice_path(@invoice), class: 'btn btn-default')
= render 'shared/title', name: t(:forward_invoice)
= form_for([:admin, @invoice], url: { action: :forward }, method: :post) do |f|
.row
.col-md-4.col-md-offset-4
= render 'shared/full_errors', object: @invoice
.form-group
= f.label :billing_email
= f.text_field :billing_email, class: 'form-control', autocomplete: 'off'
.row
.col-md-12.text-right
= button_tag(t(:forward), class: 'btn btn-warning')

View file

@ -4,6 +4,8 @@
= @invoice
.col-sm-6
%h1.text-right.text-center-xs
= link_to(t(:download), admin_invoice_download_pdf_path(@invoice), class: 'btn btn-default')
= link_to(t(:forward), admin_invoice_forward_path(@invoice), class: 'btn btn-default')
- if !@invoice.cancelled? && !@invoice.binded?
= link_to(t(:cancel), cancel_admin_invoice_path(@invoice), method: :patch, class: 'btn btn-warning')
= link_to(t(:back), admin_invoices_path, class: 'btn btn-default')

View file

@ -29,5 +29,7 @@
%hr
.row
.col-md-12.text-right
= button_tag(t(:save), class: 'btn btn-primary')
= button_tag(t(:save), class: 'btn btn-warning')
- if !f.object.new_record? && can?(:delete, f.object)
= link_to t(:delete), admin_pricelist_path(f.object),
method: :delete, data: { confirm: t(:are_you_sure_destroy) }, class: 'btn btn-danger'

View file

@ -0,0 +1,10 @@
= 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
%hr
.row
.col-md-12.text-right
%button.btn.btn-warning=t(:save)

View file

@ -21,6 +21,7 @@
= render 'setting_row', var: :dnskeys_max_count
= render 'setting_row', var: :ns_min_count
= render 'setting_row', var: :ns_max_count
= render 'setting_row', var: :expire_pending_confirmation
.panel.panel-default
.panel-heading.clearfix
@ -36,6 +37,22 @@
= render 'setting_row', var: :expire_warning_period
= render 'setting_row', var: :redemption_grace_period
.panel.panel-default
.panel-heading.clearfix
= t(:other)
.table-responsive
%table.table.table-hover.table-bordered.table-condensed
%thead
%tr
%th{class: 'col-xs-6'}= t(:setting)
%th{class: 'col-xs-6'}= t(:value)
%tbody
= render 'setting_row', var: :transfer_wait_time
= render 'setting_row', var: :ds_algorithm
= render 'setting_row', var: :client_side_status_editing_enabled
= render 'setting_row', var: :api_ip_whitelist_enabled
= render 'setting_row', var: :registrar_ip_whitelist_enabled
.panel.panel-default
.panel-heading.clearfix
= t(:billing_settings)
@ -78,21 +95,6 @@
= render 'setting_row', var: :registry_zip
= render 'setting_row', var: :registry_country_code
.panel.panel-default
.panel-heading.clearfix
= t(:other)
.table-responsive
%table.table.table-hover.table-bordered.table-condensed
%thead
%tr
%th{class: 'col-xs-6'}= t(:setting)
%th{class: 'col-xs-6'}= t(:value)
%tbody
= render 'setting_row', var: :transfer_wait_time
= render 'setting_row', var: :ds_algorithm
= render 'setting_row', var: :client_side_status_editing_enabled
= render 'setting_row', var: :api_ip_whitelist_enabled
= render 'setting_row', var: :registrar_ip_whitelist_enabled
.row
.col-md-12.text-right
%button.btn.btn-primary=t(:save)

View file

@ -4,7 +4,7 @@ Registrisse laekus taotlus domeeni <%= @domain.name %> kustutamiseks. Palun veen
<br><br>
Muudatuse kinnitamiseks külastage palun allolevat võrgulehekülge, kontrollige uuesti üle muudatuse andmed ning vajutage nuppu kinnitan:
<br><br>
Taotlus on aktiivne <48> tundi ja lükatakse automaatselt tagasi kui te seda enne ise ei kinnita või tagasi lükka.<br>
Taotlus on aktiivne <%= Setting.expire_pending_confirmation %> tundi ja lükatakse automaatselt tagasi kui te seda enne ise ei kinnita või tagasi lükka.<br>
<%= link_to @verification_url, @verification_url %>
<br><br>
Lugupidamisega<br>
@ -19,7 +19,7 @@ Application for deletion of your domain <%= @domain.name %> has been filed. Plea
To confirm the update please visit this website, once again review the data and press approve:<br>
<%= link_to @verification_url, @verification_url %>
<br><br>
The application will remain in pending status for <48> hrs and will be automaticcally rejected if it is not approved nor rejected before.
The application will remain in pending status for <%= Setting.expire_pending_confirmation %> hrs and will be automaticcally rejected if it is not approved nor rejected before.
<br><br>
Best Regards,<br>
Estonian Internet Foundation

View file

@ -4,7 +4,7 @@ Registrisse laekus taotlus domeeni <%= @domain.name %> kustutamiseks. Palun veen
Muudatuse kinnitamiseks külastage palun allolevat võrgulehekülge, kontrollige uuesti üle muudatuse andmed ning vajutage nuppu kinnitan:
Taotlus on aktiivne <48> tundi ja lükatakse automaatselt tagasi kui te seda enne ise ei kinnita või tagasi lükka.
Taotlus on aktiivne <%= Setting.expire_pending_confirmation %> tundi ja lükatakse automaatselt tagasi kui te seda enne ise ei kinnita või tagasi lükka.
<%= link_to @verification_url, @verification_url %>
Lugupidamisega
@ -19,7 +19,7 @@ Application for deletion of your domain <%= @domain.name %> has been filed. Plea
To confirm the update please visit this website, once again review the data and press approve:
<%= link_to @verification_url, @verification_url %>
The application will remain in pending status for <48> hrs and will be automaticcally rejected if it is not approved nor rejected before.
The application will remain in pending status for <%= Setting.expire_pending_confirmation %> hrs and will be automaticcally rejected if it is not approved nor rejected before.
Best Regards,
Estonian Internet Foundation

View file

@ -13,7 +13,9 @@ Tänav: <%= @domain.registrant_street %><br>
Linn: <%= @domain.registrant_city %><br>
Riik: <%= @domain.registrant_country %>
<br><br>
Taotlus on aktiivne <%= Setting.expire_pending_confirmation %> tundi ja lükatakse automaatselt tagasi kui te seda enne ise ei kinnita või tagasi lükka.<br>
Muudatuse kinnitamiseks külastage palun allolevat võrgulehekülge, kontrollige uuesti üle muudatuse andmed ning vajutage nuppu kinnitan:<br>
<%= link_to @verification_url, @verification_url %>
<br><br>
Lugupidamisega<br>
@ -36,6 +38,7 @@ Street: <%= @domain.registrant_street %><br>
City: <%= @domain.registrant_city %><br>
Country: <%= @domain.registrant_country %>
<br><br>
The application will remain in pending status for <%= Setting.expire_pending_confirmation %> hrs and will be automaticcally rejected if it is not approved nor rejected before.<br>
To confirm the update please visit this website, once again review the data and press approve:<br>
<%= link_to @verification_url, @verification_url %>
<br><br>

View file

@ -13,6 +13,7 @@ Tänav: <%= @domain.registrant_street %>
Linn: <%= @domain.registrant_city %>
Riik: <%= @domain.registrant_country %>
Taotlus on aktiivne <%= Setting.expire_pending_confirmation %> tundi ja lükatakse automaatselt tagasi kui te seda enne ise ei kinnita või tagasi lükka.
Muudatuse kinnitamiseks külastage palun allolevat võrgulehekülge, kontrollige uuesti üle muudatuse andmed ning vajutage nuppu kinnitan:
<%= @verification_url %>
@ -36,6 +37,7 @@ Street: <%= @domain.registrant_street %>
City: <%= @domain.registrant_city %>
Country: <%= @domain.registrant_country %>
The application will remain in pending status for <%= Setting.expire_pending_confirmation %> hrs and will be automaticcally rejected if it is not approved nor rejected before.
To confirm the update please visit this website, once again review the data and press approve:
<%= @verification_url %>

View file

@ -0,0 +1,39 @@
Tere,
<br><br>
Domeeni <%= @domain.name %> registreerija vahetuse taotlus on kinnitatud ning andmed registris uuendatud.
<br><br>
Uued registreerija andmed:<br>
Nimi: <%= @domain.registrant_name %><br>
<% if @domain.registrant.priv? %>
Isikukood: <%= @domain.registrant_ident %><br>
<% else %>
Äriregistrikood: <%= @domain.registrant_ident %><br>
<% end %>
Epost: <%= @domain.registrant_email %><br>
Tänav: <%= @domain.registrant_street %><br>
Linn: <%= @domain.registrant_city %><br>
Riik: <%= @domain.registrant_country %>
<br><br>
Lugupidamisega<br>
Eesti Interneti SA
<br><br>
<hr>
<br><br>
Hi,
<br><br>
Process for changing registrant of the domain <%= @domain.name %> has been approved and the data in the registry is updated.
<br><br>
New registrant:<br>
Name: <%= @domain.registrant_name %><br>
<% if @domain.registrant.priv? %>
Personal code: <%= @domain.registrant_ident %><br>
<% else %>
Business Registry code: <%= @domain.registrant_ident %><br>
<% end %>
E-mail: <%= @domain.registrant_email %><br>
Street: <%= @domain.registrant_street %><br>
City: <%= @domain.registrant_city %><br>
Country: <%= @domain.registrant_country %>
<br><br>
Best Regards,<br>
Estonian Internet Foundation

View file

@ -0,0 +1,39 @@
Tere,
Domeeni <%= @domain.name %> registreerija vahetuse taotlus on kinnitatud ning andmed registris uuendatud.
Uued registreerija andmed:
Nimi: <%= @domain.registrant_name %>
<% if @domain.registrant.priv? %>
Isikukood: <%= @domain.registrant_ident %>
<% else %>
Äriregistrikood: <%= @domain.registrant_ident %>
<% end %>
Epost: <%= @domain.registrant_email %>
Tänav: <%= @domain.registrant_street %>
Linn: <%= @domain.registrant_city %>
Riik: <%= @domain.registrant_country %>
Lugupidamisega
Eesti Interneti SA
--------------------------------------
Hi,
Process for changing registrant of the domain <%= @domain.name %> has been approved and the data in the registry is updated.
New registrant:
Name: <%= @domain.registrant_name %>
<% if @domain.registrant.priv? %>
Personal code: <%= @domain.registrant_ident %>
<% else %>
Business Registry code: <%= @domain.registrant_ident %>
<% end %>
E-mail: <%= @domain.registrant_email %>
Street: <%= @domain.registrant_street %>
City: <%= @domain.registrant_city %>
Country: <%= @domain.registrant_country %>
Best Regards,
Estonian Internet Foundation

View file

@ -60,6 +60,7 @@
%li= link_to t(:settings), admin_settings_path
%li= link_to t(:zonefile), admin_zonefile_settings_path
%li= link_to t(:blocked_domains), admin_blocked_domains_path
%li= link_to t(:reserved_domains), admin_reserved_domains_path
-# %li= link_to t(: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

View file

@ -1,29 +1,67 @@
- content_for :actions do
= link_to(t(:back_to_billing), registrar_invoices_path, class: 'btn btn-default')
= link_to(t(:export_csv), url_for(params.merge(format: 'csv')), class: 'btn btn-default')
= render 'shared/title', name: t(:account_activity)
.row
.col-md-12
= search_form_for @q, url: [:registrar, :account_activities], html: { style: 'margin-bottom: 0;' } do |f|
.row
.col-md-6
.form-group
= f.label t(:activity_type)
= f.select :activity_type_in, AccountActivity.types_for_select, {}, class: 'form-control js-combobox', placeholder: t(:choose), multiple: true
.col-md-6
.form-group
= f.label t(:description)
= f.search_field :description_cont, class: 'form-control', placeholder: t(:description), autocomplete: 'off'
.row
.col-md-3
.form-group
= f.label t(:receipt_date_from)
= f.search_field :created_at_gteq, value: params[:q][:created_at_gteq], class: 'form-control datepicker', placeholder: t(:receipt_date_from), autocomplete: 'off'
.col-md-3
.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;'}
%button.btn.btn-default
&nbsp;
%span.glyphicon.glyphicon-search
&nbsp;
%button.btn.btn-default.js-reset-form
= t(:clear_fields)
%hr
.row
.col-md-12
.table-responsive
%table.table.table-hover.table-condensed
%thead
%tr
%th{class: 'col-xs-5'}= t(:description)
%th{class: 'col-xs-3'}= t(:receipt_date)
%th{class: 'col-xs-2'}= t(:invoice)
%th{class: 'col-xs-2'}= t(:sum)
%th{class: 'col-xs-5'}
= sort_link(@q, 'description')
%th{class: 'col-xs-2'}
= sort_link(@q, 'activity_type')
%th{class: 'col-xs-3'}
= sort_link(@q, 'created_at', t(:receipt_date))
%th{class: 'col-xs-2'}
= sort_link(@q, 'sum')
%tbody
- @account_activities.each do |x|
%tr
%td= x.description.present? ? x.description : '-'
%td= x.activity_type ? t(x.activity_type) : ''
%td= l(x.created_at)
- if x.invoice
%td= link_to(x.invoice, [:registrar, x.invoice])
- else
%td \-
- c = x.sum > 0.0 ? 'text-success' : 'text-danger'
- s = x.sum > 0.0 ? "+#{x.sum} #{x.currency}" : "#{x.sum} #{x.currency}"
%td{class: c}= s
.row
.col-md-12
= paginate @account_activities
:coffee
$(".js-reset-form").on "click", (e) ->
e.preventDefault();
window.location = "#{registrar_account_activities_path}"

View file

@ -23,3 +23,10 @@
= select_tag "domain[registrant]",
options_for_select(@contacts_autocomplete_map, selected: @domain_params[:registrant]),
include_blank: true, class: 'js-combobox', required: true
- unless params[:domain_name]
.form-group
.col-md-3.control-label
= label_tag :domain_reserved_pw, t(:reserved_pw)
.col-md-7
= text_field_tag('domain[reserved_pw]', @domain_params[:reserved_pw], class: 'form-control')

View file

@ -22,6 +22,6 @@
= file_field_tag 'legal_document'
.form-group
.col-md-10.text-right
%button.btn.btn-warning{ name: 'query' }= t(:transfer)
%button.btn.btn-warning{ name: 'request' }= t(:transfer)
/%button.btn.btn-warning{ name: 'approve' }= t(:approve)
/%button.btn.btn-warning{ name: 'reject' }= t(:reject)

View file

@ -31,8 +31,6 @@ bundle install
RAILS_ENV=test bundle exec rake db:all:drop
RAILS_ENV=test bundle exec rake db:all:setup
RAILS_ENV=test bundle exec rake zonefile:replace_procedure
RAILS_ENV=test bundle exec rake assets:precompile
echo "GIT_LAST_COMMITS"
git log --pretty='%s (%cn, %cr)' --abbrev-commit --graph --decorate -n 20 --no-color
@ -44,7 +42,7 @@ RCODE=$?
echo "END_OF_RUBOCOP_RESULTS"
echo "TEST_RESULTS"
# basic test
# basic tests without EPP
# ROBOT=true bundle exec rake
# all tests with EPP

View file

@ -16,6 +16,7 @@ set :deploy_to, '$HOME/registry'
set :repository, 'https://github.com/domify/registry' # dev repo
set :branch, 'master'
set :rails_env, 'alpha'
set :que_restart, true
# alpha branch, only use for heavy debugging
task :epp do
@ -24,6 +25,7 @@ task :epp do
set :repository, 'https://github.com/domify/registry' # dev repo
set :branch, 'master'
set :rails_env, 'alpha'
set :que_restart, false
end
# alpha branch, only use for heavy debugging
@ -33,6 +35,7 @@ task :registrar do
set :repository, 'https://github.com/domify/registry' # dev repo
set :branch, 'master'
set :rails_env, 'alpha'
set :que_restart, false
end
# alpha branch, only use for heavy debugging
@ -42,6 +45,7 @@ task :registrant do
set :repository, 'https://github.com/domify/registry' # dev repo
set :branch, 'master'
set :rails_env, 'alpha'
set :que_restart, false
end
# staging
@ -51,6 +55,7 @@ task :st do
set :repository, 'https://github.com/internetee/registry' # production repo
set :branch, 'staging'
set :rails_env, 'staging'
set :que_restart, true
end
# staging
@ -60,6 +65,7 @@ task :eppst do
set :repository, 'https://github.com/internetee/registry' # production repo
set :branch, 'staging'
set :rails_env, 'staging'
set :que_restart, false
end
# staging
@ -69,6 +75,7 @@ task :registrarst do
set :repository, 'https://github.com/internetee/registry' # production repo
set :branch, 'staging'
set :rails_env, 'staging'
set :que_restart, false
end
# staging
@ -78,6 +85,7 @@ task :registrantst do
set :repository, 'https://github.com/internetee/registry' # production repo
set :branch, 'staging'
set :rails_env, 'staging'
set :que_restart, false
end
# production
@ -87,6 +95,7 @@ task :pr do
set :repository, 'https://github.com/internetee/registry' # production repo
set :branch, 'master'
set :rails_env, 'production'
set :que_restart, true
end
# production
@ -96,6 +105,7 @@ task :epppr do
set :repository, 'https://github.com/internetee/registry' # production repo
set :branch, 'master'
set :rails_env, 'production'
set :que_restart, false
end
# production
@ -105,6 +115,7 @@ task :registrarpr do
set :repository, 'https://github.com/internetee/registry' # production repo
set :branch, 'master'
set :rails_env, 'production'
set :que_restart, false
end
# production
@ -114,6 +125,7 @@ task :registrantpr do
set :repository, 'https://github.com/internetee/registry' # production repo
set :branch, 'master'
set :rails_env, 'production'
set :que_restart, false
end
# Manually create these paths in shared/ (eg: shared/config/database.yml) in your server.
@ -193,6 +205,7 @@ task deploy: :environment do
to :launch do
invoke :restart
invoke :'deploy:cleanup'
queue! "QUE_WORKER_COUNT=1 #{rake} daemon:que:restart" if que_restart
end
end
end

View file

@ -10,6 +10,7 @@ if con.present? && con.table_exists?('settings')
Setting.save_default(:admin_contacts_max_count, 10)
Setting.save_default(:tech_contacts_min_count, 1)
Setting.save_default(:tech_contacts_max_count, 10)
Setting.save_default(:expire_pending_confirmation, 48)
Setting.save_default(:ds_algorithm, 2)
Setting.save_default(:ds_data_allowed, true)

View file

@ -60,6 +60,8 @@ en:
ds_data_not_allowed: 'dsData object is not allowed'
ds_data_with_key_not_allowed: 'dsData object with key data is not allowed'
key_data_not_allowed: 'keyData object is not allowed'
required_parameter_missing_reserved: 'Required parameter missing; reserved>pw element required for reserved domains'
invalid_auth_information_reserved: 'Invalid authorization information; invalid reserved>pw value'
name_dirty:
invalid: 'Domain name is invalid'
reserved: 'Domain name is reserved'
@ -238,7 +240,7 @@ en:
errors:
messages:
blank: 'is missing'
epp_domain_reserved: 'Domain name is reserved or restricted'
epp_domain_reserved: 'Domain name is reserved'
epp_obj_does_not_exist: 'Object does not exist'
epp_command_failed: 'Command failed'
epp_authorization_error: 'Authorization error'
@ -289,6 +291,7 @@ en:
description: 'Description'
delete: 'Delete'
are_you_sure: 'Are you sure?'
are_you_sure_destroy: 'You are going to delete, are you sure?'
back: 'Back'
new_domain: 'New domain'
registrar_name: 'Registrar name'
@ -854,3 +857,16 @@ en:
registry_zip: 'Postcode'
registry_country_code: 'Country'
blocked_domains: 'Blocked domains'
billing_failure_credit_balance_low: 'Billing failure - credit balance low'
create: 'Create'
activity_type: 'Activity type'
receipt_date_from: 'Receipt date from'
receipt_date_until: 'Receipt date until'
add_credit: 'Add credit'
export_csv: 'Export CSV'
reserved_domains: 'Reserved domains'
invalid_yaml: 'Invalid YAML'
reserved_pw: 'Reserved pw'
no_transfers_found: 'No transfers found'
parameter_value_range_error: 'Parameter value range error: %{key}'
domain_registrant_updated: 'Domeeni %{name} registreerija vahetus teostatud / Registrant change of %{name} has been finished.'

View file

@ -176,7 +176,9 @@ Rails.application.routes.draw do
end
resources :invoices do
get 'download_pdf'
patch 'cancel', on: :member
match 'forward', via: [:post, :get]
end
resources :domains do
@ -190,6 +192,7 @@ Rails.application.routes.draw do
resources :settings
resources :blocked_domains
resources :reserved_domains
resources :registrars do
resources :api_users

View file

@ -16,28 +16,38 @@ every 10.minutes do
runner 'ZonefileSetting.generate_zonefiles'
end
every 6.months, at: '12pm' do
every 6.months, at: '12:01am' do
runner 'Contact.destroy_orphans'
end
every :day, at: '12:10pm' do
every :day, at: '12:10am' do
runner 'Invoice.cancel_overdue_invoices'
end
every :day, at: '12:15pm' do
every :day, at: '12:15am' do
runner 'Domain.expire_domains'
end
every :day, at: '12:20am' do
runner 'Domain.clean_expired_pendings'
end
every 3.hours do
runner 'Certificate.update_crl'
end
every :hour do
runner 'Domain.start_expire_period'
runner 'Domain.start_redemption_grace_period'
runner 'Domain.start_delete_period'
end
every 42.minutes do
runner 'Domain.destroy_delete_candidates'
end
every 45.minutes do
runner 'Domain.start_expire_period'
end
every 50.minutes do
runner 'Domain.start_delete_period'
end
every 52.minutes do
runner 'Domain.start_redemption_grace_period'
end

View file

@ -2,7 +2,7 @@ class AddReservedDomains < ActiveRecord::Migration
def up
create_table :reserved_domains do |t|
t.string :name
t.timestamps
t.timestamps null: false
end
domains = %w(

View file

@ -0,0 +1,5 @@
class IncreasePrecisionOfPricelist < ActiveRecord::Migration
def change
change_column :pricelists, :price_cents, :decimal, precision: 10, scale: 2
end
end

View file

@ -0,0 +1,5 @@
class AddActivityTypeToAccountActivities < ActiveRecord::Migration
def change
add_column :account_activities, :activity_type, :string
end
end

View file

@ -0,0 +1,6 @@
class RefactorReservedDomains < ActiveRecord::Migration
def change
remove_column :reserved_domains, :name
add_column :reserved_domains, :names, :hstore
end
end

View file

@ -0,0 +1,11 @@
class IncreaseDecimalPrecision < ActiveRecord::Migration
def change
change_column :account_activities, :sum, :decimal, precision: 10, scale: 2
change_column :accounts, :balance, :decimal, precision: 10, scale: 2, default: 0.0, null: false
change_column :bank_transactions, :sum, :decimal, precision: 10, scale: 2
change_column :banklink_transactions, :vk_amount, :decimal, precision: 10, scale: 2
change_column :invoice_items, :price, :decimal, precision: 10, scale: 2
change_column :invoices, :vat_prc, :decimal, precision: 10, scale: 2
change_column :invoices, :sum_cache, :decimal, precision: 10, scale: 2
end
end

View file

@ -0,0 +1,5 @@
class AddReservedFieldToDomain < ActiveRecord::Migration
def change
add_column :domains, :reserved, :boolean, default: false
end
end

View file

@ -0,0 +1,5 @@
class AddLogPricelistIdToAccountActivity < ActiveRecord::Migration
def change
add_column :account_activities, :log_pricelist_id, :integer
end
end

View file

@ -11,15 +11,16 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150612123111) do
ActiveRecord::Schema.define(version: 20150713113436) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
enable_extension "hstore"
create_table "account_activities", force: :cascade do |t|
t.integer "account_id"
t.integer "invoice_id"
t.decimal "sum", precision: 8, scale: 2
t.decimal "sum", precision: 10, scale: 2
t.string "currency"
t.integer "bank_transaction_id"
t.datetime "created_at"
@ -27,6 +28,8 @@ ActiveRecord::Schema.define(version: 20150612123111) do
t.string "description"
t.string "creator_str"
t.string "updator_str"
t.string "activity_type"
t.integer "log_pricelist_id"
end
add_index "account_activities", ["account_id"], name: "index_account_activities_on_account_id", using: :btree
@ -36,7 +39,7 @@ ActiveRecord::Schema.define(version: 20150612123111) do
create_table "accounts", force: :cascade do |t|
t.integer "registrar_id"
t.string "account_type"
t.decimal "balance", precision: 8, scale: 2, default: 0.0, null: false
t.decimal "balance", precision: 10, scale: 2, default: 0.0, null: false
t.datetime "created_at"
t.datetime "updated_at"
t.string "currency"
@ -98,7 +101,7 @@ ActiveRecord::Schema.define(version: 20150612123111) do
t.string "buyer_name"
t.string "document_no"
t.string "description"
t.decimal "sum", precision: 8, scale: 2
t.decimal "sum", precision: 10, scale: 2
t.string "reference_no"
t.datetime "paid_at"
t.datetime "created_at"
@ -114,7 +117,7 @@ ActiveRecord::Schema.define(version: 20150612123111) do
t.string "vk_rec_id"
t.string "vk_stamp"
t.string "vk_t_no"
t.decimal "vk_amount", precision: 8, scale: 2
t.decimal "vk_amount", precision: 10, scale: 2
t.string "vk_curr"
t.string "vk_rec_acc"
t.string "vk_rec_name"
@ -131,6 +134,14 @@ ActiveRecord::Schema.define(version: 20150612123111) do
t.datetime "updated_at"
end
create_table "blocked_domains", force: :cascade do |t|
t.string "names", array: true
t.datetime "created_at"
t.datetime "updated_at"
t.string "creator_str"
t.string "updator_str"
end
create_table "cached_nameservers", id: false, force: :cascade do |t|
t.string "hostname", limit: 255
t.string "ipv4", limit: 255
@ -188,6 +199,7 @@ ActiveRecord::Schema.define(version: 20150612123111) do
t.string "country_code"
t.string "state"
t.integer "legacy_id"
t.string "statuses", array: true
end
add_index "contacts", ["code"], name: "index_contacts_on_code", using: :btree
@ -314,6 +326,7 @@ ActiveRecord::Schema.define(version: 20150612123111) do
t.json "pending_json"
t.datetime "force_delete_at"
t.string "statuses", array: true
t.boolean "reserved", default: false
end
add_index "domains", ["delete_at"], name: "index_domains_on_delete_at", using: :btree
@ -339,7 +352,7 @@ ActiveRecord::Schema.define(version: 20150612123111) do
t.string "description", null: false
t.string "unit"
t.integer "amount"
t.decimal "price", precision: 8, scale: 2
t.decimal "price", precision: 10, scale: 2
t.datetime "created_at"
t.datetime "updated_at"
t.string "creator_str"
@ -357,7 +370,7 @@ ActiveRecord::Schema.define(version: 20150612123111) do
t.string "currency", null: false
t.string "description"
t.string "reference_no"
t.decimal "vat_prc", precision: 8, scale: 2, null: false
t.decimal "vat_prc", precision: 10, scale: 2, null: false
t.datetime "paid_at"
t.integer "seller_id"
t.string "seller_name", null: false
@ -390,7 +403,7 @@ ActiveRecord::Schema.define(version: 20150612123111) do
t.string "updator_str"
t.integer "number"
t.datetime "cancelled_at"
t.decimal "sum_cache", precision: 8, scale: 2
t.decimal "sum_cache", precision: 10, scale: 2
end
add_index "invoices", ["buyer_id"], name: "index_invoices_on_buyer_id", using: :btree
@ -521,6 +534,21 @@ ActiveRecord::Schema.define(version: 20150612123111) do
add_index "log_bank_transactions", ["item_type", "item_id"], name: "index_log_bank_transactions_on_item_type_and_item_id", using: :btree
add_index "log_bank_transactions", ["whodunnit"], name: "index_log_bank_transactions_on_whodunnit", using: :btree
create_table "log_blocked_domains", force: :cascade do |t|
t.string "item_type", null: false
t.integer "item_id", null: false
t.string "event", null: false
t.string "whodunnit"
t.json "object"
t.json "object_changes"
t.datetime "created_at"
t.string "session"
t.json "children"
end
add_index "log_blocked_domains", ["item_type", "item_id"], name: "index_log_blocked_domains_on_item_type_and_item_id", using: :btree
add_index "log_blocked_domains", ["whodunnit"], name: "index_log_blocked_domains_on_whodunnit", using: :btree
create_table "log_certificates", force: :cascade do |t|
t.string "item_type", null: false
t.integer "item_id", null: false
@ -896,7 +924,7 @@ ActiveRecord::Schema.define(version: 20150612123111) do
create_table "pricelists", force: :cascade do |t|
t.string "desc"
t.string "category"
t.decimal "price_cents", precision: 8, scale: 2, default: 0.0, null: false
t.decimal "price_cents", precision: 10, scale: 2, default: 0.0, null: false
t.string "price_currency", default: "EUR", null: false
t.datetime "valid_from"
t.datetime "valid_to"
@ -960,11 +988,11 @@ ActiveRecord::Schema.define(version: 20150612123111) do
add_index "registrars", ["code"], name: "index_registrars_on_code", using: :btree
create_table "reserved_domains", force: :cascade do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
t.string "creator_str"
t.string "updator_str"
t.hstore "names"
end
create_table "settings", force: :cascade do |t|
@ -1002,7 +1030,7 @@ ActiveRecord::Schema.define(version: 20150612123111) do
t.text "crt"
t.string "type"
t.string "registrant_ident"
t.string "encrypted_password", default: "", null: false
t.string "encrypted_password", default: ""
t.datetime "remember_created_at"
t.integer "failed_attempts", default: 0, null: false
t.datetime "locked_at"

View file

@ -23,8 +23,183 @@ CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
--
-- Name: hstore; Type: EXTENSION; Schema: -; Owner: -
--
CREATE EXTENSION IF NOT EXISTS hstore WITH SCHEMA public;
--
-- Name: EXTENSION hstore; Type: COMMENT; Schema: -; Owner: -
--
COMMENT ON EXTENSION hstore IS 'data type for storing sets of (key, value) pairs';
SET search_path = public, pg_catalog;
--
-- Name: generate_zonefile(character varying); Type: FUNCTION; Schema: public; Owner: -
--
CREATE FUNCTION generate_zonefile(i_origin character varying) RETURNS text
LANGUAGE plpgsql
AS $_$
DECLARE
zone_header text := concat('$ORIGIN ', i_origin, '.');
serial_num varchar;
include_filter varchar := '';
exclude_filter varchar := '';
tmp_var text;
ret text;
BEGIN
-- define filters
include_filter = '%.' || i_origin;
-- for %.%.%
IF i_origin ~ '\.' THEN
exclude_filter := '';
-- for %.%
ELSE
exclude_filter := '%.%.' || i_origin;
END IF;
SELECT ROUND(extract(epoch from now() at time zone 'utc')) INTO serial_num;
-- zonefile header
SELECT concat(
format('%-10s', '$ORIGIN .'), chr(10),
format('%-10s', '$TTL'), zf.ttl, chr(10), chr(10),
format('%-10s', i_origin || '.'), 'IN SOA ', zf.master_nameserver, '. ', zf.email, '. (', chr(10),
format('%-17s', ''), format('%-12s', serial_num), '; serial number', chr(10),
format('%-17s', ''), format('%-12s', zf.refresh), '; refresh, seconds', chr(10),
format('%-17s', ''), format('%-12s', zf.retry), '; retry, seconds', chr(10),
format('%-17s', ''), format('%-12s', zf.expire), '; expire, seconds', chr(10),
format('%-17s', ''), format('%-12s', zf.minimum_ttl), '; minimum TTL, seconds', chr(10),
format('%-17s', ''), ')'
) FROM zonefile_settings zf WHERE i_origin = zf.origin INTO tmp_var;
ret = concat(tmp_var, chr(10), chr(10));
-- ns records
SELECT array_to_string(
array(
SELECT concat(d.name_puny, '. IN NS ', ns.hostname, '.')
FROM domains d
JOIN nameservers ns ON ns.domain_id = d.id
WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter OR d.name = i_origin
ORDER BY d.name
),
chr(10)
) INTO tmp_var;
ret := concat(ret, '; Zone NS Records', chr(10), tmp_var, chr(10), chr(10));
-- a glue records for origin nameservers
SELECT array_to_string(
array(
SELECT concat(ns.hostname, '. IN A ', ns.ipv4)
FROM nameservers ns
JOIN domains d ON d.id = ns.domain_id
WHERE d.name = i_origin
AND ns.hostname LIKE '%.' || d.name
AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> ''
), chr(10)
) INTO tmp_var;
ret := concat(ret, '; Zone A Records', chr(10), tmp_var);
-- a glue records for other nameservers
SELECT array_to_string(
array(
SELECT concat(ns.hostname, '. IN A ', ns.ipv4)
FROM nameservers ns
JOIN domains d ON d.id = ns.domain_id
WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter
AND ns.hostname LIKE '%.' || d.name
AND d.name <> i_origin
AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> ''
AND NOT EXISTS ( -- filter out glue records that already appeared in origin glue recrods
SELECT 1 FROM nameservers nsi
JOIN domains di ON nsi.domain_id = di.id
WHERE di.name = i_origin
AND nsi.hostname = ns.hostname
)
), chr(10)
) INTO tmp_var;
-- TODO This is a possible subtitition to the previous query, stress testing is needed to see which is faster
-- SELECT ns.*
-- FROM nameservers ns
-- JOIN domains d ON d.id = ns.domain_id
-- WHERE d.name LIKE '%ee' AND d.name NOT LIKE '%pri.ee'
-- AND ns.hostname LIKE '%.' || d.name
-- AND d.name <> 'ee'
-- AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> ''
-- AND ns.hostname NOT IN (
-- SELECT ns.hostname FROM domains d JOIN nameservers ns ON d.id = ns.domain_id WHERE d.name = 'ee'
-- )
ret := concat(ret, chr(10), tmp_var, chr(10), chr(10));
-- aaaa glue records for origin nameservers
SELECT array_to_string(
array(
SELECT concat(ns.hostname, '. IN AAAA ', ns.ipv6)
FROM nameservers ns
JOIN domains d ON d.id = ns.domain_id
WHERE d.name = i_origin
AND ns.hostname LIKE '%.' || d.name
AND ns.ipv6 IS NOT NULL AND ns.ipv6 <> ''
), chr(10)
) INTO tmp_var;
ret := concat(ret, '; Zone AAAA Records', chr(10), tmp_var);
-- aaaa glue records for other nameservers
SELECT array_to_string(
array(
SELECT concat(ns.hostname, '. IN AAAA ', ns.ipv6)
FROM nameservers ns
JOIN domains d ON d.id = ns.domain_id
WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter
AND ns.hostname LIKE '%.' || d.name
AND d.name <> i_origin
AND ns.ipv6 IS NOT NULL AND ns.ipv6 <> ''
AND NOT EXISTS ( -- filter out glue records that already appeared in origin glue recrods
SELECT 1 FROM nameservers nsi
JOIN domains di ON nsi.domain_id = di.id
WHERE di.name = i_origin
AND nsi.hostname = ns.hostname
)
), chr(10)
) INTO tmp_var;
ret := concat(ret, chr(10), tmp_var, chr(10), chr(10));
-- ds records
SELECT array_to_string(
array(
SELECT concat(
d.name_puny, '. IN DS ', dk.ds_key_tag, ' ',
dk.ds_alg, ' ', dk.ds_digest_type, ' ( ', dk.ds_digest, ' )'
)
FROM domains d
JOIN dnskeys dk ON dk.domain_id = d.id
WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter AND dk.flags = 257
),
chr(10)
) INTO tmp_var;
ret := concat(ret, '; Zone DS Records', chr(10), tmp_var, chr(10));
RETURN ret;
END;
$_$;
SET default_tablespace = '';
SET default_with_oids = false;
@ -37,14 +212,16 @@ CREATE TABLE account_activities (
id integer NOT NULL,
account_id integer,
invoice_id integer,
sum numeric(8,2),
sum numeric(10,2),
currency character varying,
bank_transaction_id integer,
created_at timestamp without time zone,
updated_at timestamp without time zone,
description character varying,
creator_str character varying,
updator_str character varying
updator_str character varying,
activity_type character varying,
log_pricelist_id integer
);
@ -75,7 +252,7 @@ CREATE TABLE accounts (
id integer NOT NULL,
registrar_id integer,
account_type character varying,
balance numeric(8,2) DEFAULT 0.0 NOT NULL,
balance numeric(10,2) DEFAULT 0.0 NOT NULL,
created_at timestamp without time zone,
updated_at timestamp without time zone,
currency character varying,
@ -233,7 +410,7 @@ CREATE TABLE bank_transactions (
buyer_name character varying,
document_no character varying,
description character varying,
sum numeric(8,2),
sum numeric(10,2),
reference_no character varying,
paid_at timestamp without time zone,
created_at timestamp without time zone,
@ -274,7 +451,7 @@ CREATE TABLE banklink_transactions (
vk_rec_id character varying,
vk_stamp character varying,
vk_t_no character varying,
vk_amount numeric(8,2),
vk_amount numeric(10,2),
vk_curr character varying,
vk_rec_acc character varying,
vk_rec_name character varying,
@ -311,6 +488,39 @@ CREATE SEQUENCE banklink_transactions_id_seq
ALTER SEQUENCE banklink_transactions_id_seq OWNED BY banklink_transactions.id;
--
-- Name: blocked_domains; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
CREATE TABLE blocked_domains (
id integer NOT NULL,
names character varying[],
created_at timestamp without time zone,
updated_at timestamp without time zone,
creator_str character varying,
updator_str character varying
);
--
-- Name: blocked_domains_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE blocked_domains_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: blocked_domains_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE blocked_domains_id_seq OWNED BY blocked_domains.id;
--
-- Name: cached_nameservers; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
@ -421,7 +631,8 @@ CREATE TABLE contacts (
zip character varying,
country_code character varying,
state character varying,
legacy_id integer
legacy_id integer,
statuses character varying[]
);
@ -733,7 +944,8 @@ CREATE TABLE domains (
registrant_verification_token character varying,
pending_json json,
force_delete_at timestamp without time zone,
statuses character varying[]
statuses character varying[],
reserved boolean DEFAULT false
);
@ -799,7 +1011,7 @@ CREATE TABLE invoice_items (
description character varying NOT NULL,
unit character varying,
amount integer,
price numeric(8,2),
price numeric(10,2),
created_at timestamp without time zone,
updated_at timestamp without time zone,
creator_str character varying,
@ -840,7 +1052,7 @@ CREATE TABLE invoices (
currency character varying NOT NULL,
description character varying,
reference_no character varying,
vat_prc numeric(8,2) NOT NULL,
vat_prc numeric(10,2) NOT NULL,
paid_at timestamp without time zone,
seller_id integer,
seller_name character varying NOT NULL,
@ -873,7 +1085,7 @@ CREATE TABLE invoices (
updator_str character varying,
number integer,
cancelled_at timestamp without time zone,
sum_cache numeric(8,2)
sum_cache numeric(10,2)
);
@ -1197,6 +1409,43 @@ CREATE SEQUENCE log_bank_transactions_id_seq
ALTER SEQUENCE log_bank_transactions_id_seq OWNED BY log_bank_transactions.id;
--
-- Name: log_blocked_domains; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
CREATE TABLE log_blocked_domains (
id integer NOT NULL,
item_type character varying NOT NULL,
item_id integer NOT NULL,
event character varying NOT NULL,
whodunnit character varying,
object json,
object_changes json,
created_at timestamp without time zone,
session character varying,
children json
);
--
-- Name: log_blocked_domains_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE log_blocked_domains_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: log_blocked_domains_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE log_blocked_domains_id_seq OWNED BY log_blocked_domains.id;
--
-- Name: log_certificates; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
@ -2135,7 +2384,7 @@ CREATE TABLE pricelists (
id integer NOT NULL,
"desc" character varying,
category character varying,
price_cents numeric(8,2) DEFAULT 0.0 NOT NULL,
price_cents numeric(10,2) DEFAULT 0 NOT NULL,
price_currency character varying DEFAULT 'EUR'::character varying NOT NULL,
valid_from timestamp without time zone,
valid_to timestamp without time zone,
@ -2173,8 +2422,8 @@ ALTER SEQUENCE pricelists_id_seq OWNED BY pricelists.id;
CREATE TABLE que_jobs (
priority smallint DEFAULT 100 NOT NULL,
run_at timestamp without time zone DEFAULT '2015-06-29 12:38:58.258132'::timestamp without time zone NOT NULL,
job_id bigint DEFAULT 0 NOT NULL,
run_at timestamp with time zone DEFAULT now() NOT NULL,
job_id bigint NOT NULL,
job_class text NOT NULL,
args json DEFAULT '[]'::json NOT NULL,
error_count integer DEFAULT 0 NOT NULL,
@ -2183,6 +2432,32 @@ CREATE TABLE que_jobs (
);
--
-- Name: TABLE que_jobs; Type: COMMENT; Schema: public; Owner: -
--
COMMENT ON TABLE que_jobs IS '3';
--
-- Name: que_jobs_job_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE que_jobs_job_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: que_jobs_job_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE que_jobs_job_id_seq OWNED BY que_jobs.job_id;
--
-- Name: registrant_verifications; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
@ -2274,11 +2549,11 @@ ALTER SEQUENCE registrars_id_seq OWNED BY registrars.id;
CREATE TABLE reserved_domains (
id integer NOT NULL,
name character varying,
created_at timestamp without time zone,
updated_at timestamp without time zone,
creator_str character varying,
updator_str character varying
updator_str character varying,
names hstore
);
@ -2373,7 +2648,7 @@ CREATE TABLE users (
crt text,
type character varying,
registrant_ident character varying,
encrypted_password character varying DEFAULT ''::character varying NOT NULL,
encrypted_password character varying DEFAULT ''::character varying,
remember_created_at timestamp without time zone,
failed_attempts integer DEFAULT 0 NOT NULL,
locked_at timestamp without time zone
@ -2588,6 +2863,13 @@ ALTER TABLE ONLY bank_transactions ALTER COLUMN id SET DEFAULT nextval('bank_tra
ALTER TABLE ONLY banklink_transactions ALTER COLUMN id SET DEFAULT nextval('banklink_transactions_id_seq'::regclass);
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY blocked_domains ALTER COLUMN id SET DEFAULT nextval('blocked_domains_id_seq'::regclass);
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
--
@ -2742,6 +3024,13 @@ ALTER TABLE ONLY log_bank_statements ALTER COLUMN id SET DEFAULT nextval('log_ba
ALTER TABLE ONLY log_bank_transactions ALTER COLUMN id SET DEFAULT nextval('log_bank_transactions_id_seq'::regclass);
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY log_blocked_domains ALTER COLUMN id SET DEFAULT nextval('log_blocked_domains_id_seq'::regclass);
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
--
@ -2924,6 +3213,13 @@ ALTER TABLE ONLY people ALTER COLUMN id SET DEFAULT nextval('people_id_seq'::reg
ALTER TABLE ONLY pricelists ALTER COLUMN id SET DEFAULT nextval('pricelists_id_seq'::regclass);
--
-- Name: job_id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY que_jobs ALTER COLUMN job_id SET DEFAULT nextval('que_jobs_job_id_seq'::regclass);
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
--
@ -3043,6 +3339,14 @@ ALTER TABLE ONLY banklink_transactions
ADD CONSTRAINT banklink_transactions_pkey PRIMARY KEY (id);
--
-- Name: blocked_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
ALTER TABLE ONLY blocked_domains
ADD CONSTRAINT blocked_domains_pkey PRIMARY KEY (id);
--
-- Name: certificates_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
@ -3219,6 +3523,14 @@ ALTER TABLE ONLY log_bank_transactions
ADD CONSTRAINT log_bank_transactions_pkey PRIMARY KEY (id);
--
-- Name: log_blocked_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
ALTER TABLE ONLY log_blocked_domains
ADD CONSTRAINT log_blocked_domains_pkey PRIMARY KEY (id);
--
-- Name: log_certificates_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
@ -3427,6 +3739,14 @@ ALTER TABLE ONLY pricelists
ADD CONSTRAINT pricelists_pkey PRIMARY KEY (id);
--
-- Name: que_jobs_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
ALTER TABLE ONLY que_jobs
ADD CONSTRAINT que_jobs_pkey PRIMARY KEY (queue, priority, run_at, job_id);
--
-- Name: registrant_verifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
@ -3821,6 +4141,20 @@ CREATE INDEX index_log_bank_transactions_on_item_type_and_item_id ON log_bank_tr
CREATE INDEX index_log_bank_transactions_on_whodunnit ON log_bank_transactions USING btree (whodunnit);
--
-- Name: index_log_blocked_domains_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
--
CREATE INDEX index_log_blocked_domains_on_item_type_and_item_id ON log_blocked_domains USING btree (item_type, item_id);
--
-- Name: index_log_blocked_domains_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace:
--
CREATE INDEX index_log_blocked_domains_on_whodunnit ON log_blocked_domains USING btree (whodunnit);
--
-- Name: index_log_certificates_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
--
@ -4407,6 +4741,8 @@ INSERT INTO schema_migrations (version) VALUES ('20150227092508');
INSERT INTO schema_migrations (version) VALUES ('20150227113121');
INSERT INTO schema_migrations (version) VALUES ('20150302130224');
INSERT INTO schema_migrations (version) VALUES ('20150302161712');
INSERT INTO schema_migrations (version) VALUES ('20150303130729');
@ -4465,6 +4801,8 @@ INSERT INTO schema_migrations (version) VALUES ('20150417082723');
INSERT INTO schema_migrations (version) VALUES ('20150421134820');
INSERT INTO schema_migrations (version) VALUES ('20150422090645');
INSERT INTO schema_migrations (version) VALUES ('20150422092514');
INSERT INTO schema_migrations (version) VALUES ('20150422132631');
@ -4509,6 +4847,8 @@ INSERT INTO schema_migrations (version) VALUES ('20150519115050');
INSERT INTO schema_migrations (version) VALUES ('20150519140853');
INSERT INTO schema_migrations (version) VALUES ('20150519142542');
INSERT INTO schema_migrations (version) VALUES ('20150519144118');
INSERT INTO schema_migrations (version) VALUES ('20150520163237');
@ -4517,14 +4857,28 @@ INSERT INTO schema_migrations (version) VALUES ('20150520164507');
INSERT INTO schema_migrations (version) VALUES ('20150521120145');
INSERT INTO schema_migrations (version) VALUES ('20150522164020');
INSERT INTO schema_migrations (version) VALUES ('20150525075550');
INSERT INTO schema_migrations (version) VALUES ('20150601083516');
INSERT INTO schema_migrations (version) VALUES ('20150601083800');
INSERT INTO schema_migrations (version) VALUES ('20150603141054');
INSERT INTO schema_migrations (version) VALUES ('20150603141549');
INSERT INTO schema_migrations (version) VALUES ('20150603211318');
INSERT INTO schema_migrations (version) VALUES ('20150603212659');
INSERT INTO schema_migrations (version) VALUES ('20150609093515');
INSERT INTO schema_migrations (version) VALUES ('20150609103333');
INSERT INTO schema_migrations (version) VALUES ('20150610111019');
INSERT INTO schema_migrations (version) VALUES ('20150610112238');
INSERT INTO schema_migrations (version) VALUES ('20150610144547');
@ -4533,3 +4887,23 @@ INSERT INTO schema_migrations (version) VALUES ('20150611124920');
INSERT INTO schema_migrations (version) VALUES ('20150612123111');
INSERT INTO schema_migrations (version) VALUES ('20150612125720');
INSERT INTO schema_migrations (version) VALUES ('20150701074344');
INSERT INTO schema_migrations (version) VALUES ('20150703084632');
INSERT INTO schema_migrations (version) VALUES ('20150706091724');
INSERT INTO schema_migrations (version) VALUES ('20150707103241');
INSERT INTO schema_migrations (version) VALUES ('20150707103801');
INSERT INTO schema_migrations (version) VALUES ('20150707104937');
INSERT INTO schema_migrations (version) VALUES ('20150707154543');
INSERT INTO schema_migrations (version) VALUES ('20150709092549');
INSERT INTO schema_migrations (version) VALUES ('20150713113436');

View file

@ -16,6 +16,7 @@ Application build and update
For production you probably would like to create databases to your locale, example:
create database registry_production owner registry encoding 'UTF-8' LC_COLLATE 'et_EE.utf8' LC_CTYPE 'et_EE.utf8' template template0;
create extension hstore;
Deploy overview: (database schema should be loaded and seeds should be present)

File diff suppressed because it is too large Load diff

View file

@ -38,9 +38,11 @@ Domain name mapping protocol short version:
<eis:extdata> 1 Attribute: xmlns:eis="https://raw.githubusercontent.com/internetee/registry/alpha/doc/schemas/eis-1.0.xsd"
<eis:legalDocument> 1 Base64 encoded document.
Attribute: type="pdf/bdoc/ddoc/zip/rar/gz/tar/7z"
<eis:reserved> 0-1
<eis:pw> 0-1 Required if registering a reserved domain
<clTRID> 0-1 Client transaction id
[EXAMPLE REQUEST AND RESPONSE](/doc/epp-examples.md#epp-domain-with-citizen-as-an-owner-creates-a-domain)
[EXAMPLE REQUEST AND RESPONSE](/doc/epp-examples.md#epp-domain-with-citizen-as-a-registrant-creates-a-domain)
### Domain update
@ -141,7 +143,7 @@ Domain name mapping protocol short version:
Field name Min-max Field description
----------------------- ------- -----------------
<transfer> 1
<transfer> 1 Attribute: op="request/query/approve/reject/cancel"
<domain:transfer> 1 Attribute: xmlns:domain="https://raw.githubusercontent.com/internetee/registry/alpha/doc/schemas/domain-eis-1.0.xsd"
<domain:name> 1 Domain name. Can contain unicode characters.
<domain:authInfo> 1

View file

@ -27,18 +27,18 @@ cd $APP_ROOT || exit 1
case ${1-help} in
status)
cd $APP_ROOT && RAILS_ENV=$RAILS_ENV $RUBY_BUNDLE_PATH exec rake daemon:que:status
cd $APP_ROOT && RAILS_ENV=$RAILS_ENV $RUBY_BUNDLE_PATH exec lib/daemons/que_ctl status
;;
start)
echo "$1 que monitor and server"
for i in `seq 1 $QUE_INSTANCES`; do
cd $APP_ROOT && RAILS_ENV=$RAILS_ENV $RUBY_BUNDLE_PATH exec rake daemon:que:start
cd $APP_ROOT && QUE_WORKER_COUNT=1 RAILS_ENV=$RAILS_ENV $RUBY_BUNDLE_PATH exec rake daemon:que:start
echo '.'
done
;;
stop)
echo "$1 que monitor and server"
cd $APP_ROOT && RAILS_ENV=$RAILS_ENV $RUBY_BUNDLE_PATH exec rake daemon:que:stop
cd $APP_ROOT && RAILS_ENV=$RAILS_ENV $RUBY_BUNDLE_PATH lib/daemons/que_ctl stop
;;
restart)
echo "$1 que monitor and server"

View file

@ -15,15 +15,16 @@
Child elements found in EPP commands.
-->
<element name="extdata" type="eis:legalDocAndIdentType"/>
<element name="extdata" type="eis:eisExtType"/>
<!--
Child elements supporting ident and legal documents.
Child elements supporting EIS specific values.
-->
<complexType name="legalDocAndIdentType">
<complexType name="eisExtType">
<sequence>
<element name="ident" type="eis:identType" minOccurs="0" maxOccurs="1"/>
<element name="legalDocument" type="eis:legalDocType" minOccurs="0" maxOccurs="1"/>
<element name="reserved" type="eis:reservedType" minOccurs="0" maxOccurs="1"/>
</sequence>
</complexType>
@ -31,6 +32,23 @@
Child elements of extdata
-->
<!--
Reserved for providing passwords for reserved domains
-->
<complexType name="reservedType">
<sequence>
<element name="pw" type="eis:pwType" minOccurs="0" maxOccurs="1"/>
</sequence>
</complexType>
<simpleType name="pwType">
<restriction base="normalizedString">
<minLength value="1"/>
<maxLength value="255"/>
</restriction>
</simpleType>
<!--
Legal document, encoded in base64
-->

View file

@ -3,15 +3,41 @@
ENV["RAILS_ENV"] ||= "production"
root = File.expand_path(File.dirname(__FILE__))
root = File.dirname(root) until File.exists?(File.join(root, 'config'))
root = File.dirname(root) until File.exist?(File.join(root, 'config'))
Dir.chdir(root)
require File.join(root, "config", "environment")
$running = true
Signal.trap("TERM") do
$running = false
# from que gem rake task
if defined?(::Rails) && Rails.respond_to?(:application)
# ActiveSupport's dependency autoloading isn't threadsafe, and Que uses
# multiple threads, which means that eager loading is necessary. Rails
# explicitly prevents eager loading when the environment task is invoked,
# so we need to manually eager load the app here.
Rails.application.eager_load!
end
while($running) do
Que.logger.level = Logger.const_get((ENV['QUE_LOG_LEVEL'] || 'INFO').upcase)
Que.worker_count = 1
Que.wake_interval = (ENV['QUE_WAKE_INTERVAL'] || 0.1).to_f
Que.mode = :async
# When changing how signals are caught, be sure to test the behavior with
# the rake task in tasks/safe_shutdown.rb.
stop = false
%w( INT TERM ).each do |signal|
trap(signal) { stop = true }
end
at_exit do
$stdout.puts "Finishing Que's current jobs before exiting..."
Que.worker_count = 0
Que.mode = :off
$stdout.puts "Que's jobs finished, exiting..."
end
loop do
sleep 0.01
break if stop
end

View file

@ -1,12 +1,45 @@
Rake::Task["db:schema:load"].clear
Rake::Task["db:migrate"].enhance do
if ActiveRecord::Base.schema_format == :sql
Rake::Task["db:schema:dump"].invoke
end
end
Rake::Task["db:rollback"].enhance do
if ActiveRecord::Base.schema_format == :sql
Rake::Task["db:schema:dump"].invoke
end
end
Rake::Task["db:schema:dump"].enhance do
if ActiveRecord::Base.schema_format == :sql
File.rename('db/schema.rb', 'db/schema-read-only.rb')
Rake::Task["db:structure:dump"].invoke # for users who do manually db:schema:dump
end
end
namespace :db do
namespace :schema do
task load: [:environment, :load_config] do
puts 'Only rake db:structure:load is supported and invoked. ' \
'Otherwise zonefile generation does not work nor que.'
Rake::Task["db:structure:load"].invoke
end
end
def databases
@db ||= [Rails.env, "api_log_#{Rails.env}", "whois_#{Rails.env}"]
end
def other_databases
@other_dbs ||= ["api_log_#{Rails.env}", "whois_#{Rails.env}"]
end
def schema_file(db)
case db
when Rails.env
'schema.rb'
'structure.sql' # just in case
when "api_log_#{Rails.env}"
'api_log_schema.rb'
when "whois_#{Rails.env}"
@ -25,7 +58,7 @@ namespace :db do
puts "\n---------------------------- Import seed ----------------------------------------\n"
Rake::Task['db:seed'].invoke
Rake::Task['zonefile:replace_procedure'].invoke
# Rake::Task['zonefile:replace_procedure'].invoke # not needed any more
puts "\n All done!\n\n"
end
@ -73,7 +106,10 @@ namespace :db do
namespace :schema do
desc 'Schema load for all databases: registry, api_log and whois'
task load: [:environment, :load_config] do
databases.each do |name|
puts "\n------------------------ #{Rails.env} structure loading -----------------------------\n"
Rake::Task['db:structure:load'].invoke
other_databases.each do |name|
begin
puts "\n------------------------ #{name} schema loading -----------------------------\n"
ActiveRecord::Base.clear_all_connections!
@ -89,9 +125,12 @@ namespace :db do
end
end
desc 'Schema load for all databases: registry, api_log and whois'
desc 'Schema dump for all databases: registry, api_log and whois'
task dump: [:environment, :load_config] do
databases.each do |name|
puts "\n---------------------------- #{Rails.env} structure and schema dump--------------\n"
Rake::Task['db:schema:dump'].invoke # dumps both schema and structure
other_databases.each do |name|
begin
puts "\n---------------------------- #{name} ----------------------------------------\n"
filename = "#{Rails.root}/db/#{schema_file(name)}"
@ -104,6 +143,17 @@ namespace :db do
end
end
end
# alias names
namespace :structure do
desc '(alias) Schema dump for all databases: registry, api_log and whois'
task :dump do
Rake::Task['db:all:schema:dump'].invoke
end
desc '(alias) Schema load for all databases: registry, api_log and whois'
task :load do
Rake::Task['db:all:schema:load'].invoke
end
end
end
end
end

View file

@ -5,7 +5,9 @@ describe 'EPP Domain', epp: true do
@xsd = Nokogiri::XML::Schema(File.read('doc/schemas/domain-eis-1.0.xsd'))
@epp_xml = EppXml.new(cl_trid: 'ABC-12345')
@registrar1 = Fabricate(:registrar1, code: 'REGDOMAIN1')
@registrar1.credit!({ sum: 10000 })
@registrar2 = Fabricate(:registrar2, code: 'REGDOMAIN2')
@registrar2.credit!({ sum: 10000 })
Fabricate(:api_user, username: 'registrar1', registrar: @registrar1)
Fabricate(:api_user, username: 'registrar2', registrar: @registrar2)
@ -17,10 +19,29 @@ describe 'EPP Domain', epp: true do
Fabricate(:contact, code: 'FIXED:JURIDICAL_1234', ident_type: 'bic')
Fabricate(:reserved_domain)
Fabricate(:blocked_domain)
@pricelist_reg_1_year = Fabricate(:pricelist, valid_to: nil)
@pricelist_reg_2_year = Fabricate(:pricelist, duration: '2years', price: 20, valid_to: nil)
Fabricate(:pricelist, duration: '3years', price: 30, valid_to: nil)
@pricelist_renew_1_year = Fabricate(:pricelist, operation_category: 'renew', price: 15, valid_to: nil)
Fabricate(:pricelist, operation_category: 'renew', duration: '2years', price: 35, valid_to: nil)
Fabricate(:pricelist, operation_category: 'renew', duration: '3years', price: 62, valid_to: nil)
@uniq_no = proc { @i ||= 0; @i += 1 }
end
it 'should return error if balance low' do
f = Fabricate(:pricelist, valid_to: Time.zone.now + 1.day, price: 100000)
dn = next_domain_name
response = epp_plain_request(domain_create_xml({
name: { value: dn }
}))
response[:msg].should == "Billing failure - credit balance low"
response[:result_code].should == '2104'
f.delete
end
it 'returns error if contact does not exists' do
response = epp_plain_request(domain_create_xml({
registrant: { value: 'FIXED:CITIZEN_1234' },
@ -123,6 +144,7 @@ describe 'EPP Domain', epp: true do
response[:result_code].should == '1000'
d = Domain.last
d.legal_documents.count.should == 1
d.reserved.should == false
end
# it 'creates ria.ee with valid ds record' do
@ -203,17 +225,56 @@ describe 'EPP Domain', epp: true do
xml = domain_create_xml(name: { value: '1162.ee' })
response = epp_plain_request(xml)
response[:result_code].should == '2302'
response[:msg].should == 'Domain name is reserved [name_dirty]'
response[:msg].should == 'Required parameter missing; reserved>pw element required for reserved domains'
response[:result_code].should == '2003'
response[:clTRID].should == 'ABC-12345'
xml = domain_create_xml({name: { value: '1162.ee' }}, {}, {
_anonymus: [
legalDocument: {
value: 'dGVzdCBmYWlsCg==',
attrs: { type: 'pdf' }
},
reserved: {
pw: { value: 'wrong_pw' }
}
]
})
response = epp_plain_request(xml)
response[:msg].should == 'Invalid authorization information; invalid reserved>pw value'
response[:result_code].should == '2202'
end
it 'creates a reserved domain with correct auth info' do
xml = domain_create_xml({name: { value: '1162.ee' }}, {}, {
_anonymus: [
legalDocument: {
value: 'dGVzdCBmYWlsCg==',
attrs: { type: 'pdf' }
},
reserved: {
pw: { value: 'abc' }
}
]
})
response = epp_plain_request(xml)
response[:msg].should == 'Command completed successfully'
response[:result_code].should == '1000'
d = Domain.last
d.statuses.should match_array(['ok'])
d.reserved.should == true
end
it 'does not create blocked domain' do
xml = domain_create_xml(name: { value: 'ftp.ee' })
response = epp_plain_request(xml)
response[:result_code].should == '2302'
response[:msg].should == 'Domain name is blocked [name_dirty]'
response[:result_code].should == '2302'
response[:results][0][:value].should == 'ftp.ee'
response[:clTRID].should == 'ABC-12345'
end
@ -322,15 +383,61 @@ describe 'EPP Domain', epp: true do
end
it 'creates a domain with period in days' do
xml = domain_create_xml(period_value: 365, period_unit: 'd')
old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count
xml = domain_create_xml(period: { value: '365', attrs: { unit: 'd' } })
response = epp_plain_request(xml)
response[:msg].should == 'Command completed successfully'
response[:result_code].should == '1000'
Domain.first.valid_to.should be_within(60).of(1.year.since)
Domain.last.valid_to.should be_within(60).of(1.year.since)
@registrar1.balance.should be < old_balance
@registrar1.cash_account.account_activities.count.should == old_activities + 1
a = @registrar1.cash_account.account_activities.last
a.description.should == "Create #{Domain.last.name}"
a.sum.should == -BigDecimal.new('10.0')
a.activity_type = AccountActivity::CREATE
a.log_pricelist_id.should == @pricelist_reg_1_year.id
end
it 'creates a domain with longer periods' do
old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count
xml = domain_create_xml(period: { value: '2', attrs: { unit: 'y' } })
response = epp_plain_request(xml)
response[:msg].should == 'Command completed successfully'
response[:result_code].should == '1000'
Domain.last.valid_to.should be_within(60).of(2.years.since)
@registrar1.balance.should be < old_balance
@registrar1.cash_account.account_activities.count.should == old_activities + 1
a = @registrar1.cash_account.account_activities.last
a.description.should == "Create #{Domain.last.name}"
a.sum.should == -BigDecimal.new('20.0')
a.activity_type = AccountActivity::CREATE
a.log_pricelist_id.should == @pricelist_reg_2_year.id
end
it 'creates a domain with longer periods' do
old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count
xml = domain_create_xml(period: { value: '36', attrs: { unit: 'm' } })
response = epp_plain_request(xml)
response[:msg].should == 'Command completed successfully'
response[:result_code].should == '1000'
Domain.last.valid_to.should be_within(60).of(3.years.since)
@registrar1.balance.should be < old_balance
@registrar1.cash_account.account_activities.count.should == old_activities + 1
a = @registrar1.cash_account.account_activities.last
a.description.should == "Create #{Domain.last.name}"
a.sum.should == -BigDecimal.new('30.0')
a.activity_type = AccountActivity::CREATE
end
it 'does not create a domain with invalid period' do
old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count
xml = domain_create_xml({
period: { value: '367', attrs: { unit: 'd' } }
})
@ -339,6 +446,8 @@ describe 'EPP Domain', epp: true do
response[:results][0][:result_code].should == '2306'
response[:results][0][:msg].should == 'Period must add up to 1, 2 or 3 years [period]'
response[:results][0][:value].should == '367'
@registrar1.balance.should == old_balance
@registrar1.cash_account.account_activities.count.should == old_activities
end
it 'creates a domain with multiple dnskeys' do
@ -733,7 +842,7 @@ describe 'EPP Domain', epp: true do
xml = domain_transfer_xml({
name: { value: domain.name },
authInfo: { pw: { value: pw } }
}, 'query', {
}, 'request', {
_anonymus: [
legalDocument: {
value: 'dGVzdCBmYWlsCg==',
@ -781,7 +890,7 @@ describe 'EPP Domain', epp: true do
xml = domain_transfer_xml({
name: { value: domain.name },
authInfo: { pw: { value: pw } }
}, 'query', {
}, 'request', {
_anonymus: [
legalDocument: {
value: 'dGVzdCBmYWlsCg==',
@ -859,7 +968,7 @@ describe 'EPP Domain', epp: true do
xml = domain_transfer_xml({
name: { value: domain.name },
authInfo: { pw: { value: pw } }
}, 'query', {
}, 'request', {
_anonymus: [
legalDocument: {
value: 'dGVzdCBmYWlsCg==',
@ -1295,7 +1404,7 @@ describe 'EPP Domain', epp: true do
xml = domain_transfer_xml({
name: { value: domain.name },
authInfo: { pw: { value: 'test' } }
}, 'query', {
}, 'request', {
_anonymus: [
legalDocument: {
value: 'dGVzdCBmYWlsCg==',
@ -1309,12 +1418,12 @@ describe 'EPP Domain', epp: true do
response[:msg].should == 'Authorization error'
end
it 'ignores transfer wha registrant registrar requests transfer' do
it 'ignores transfer when domain already belongs to registrar' do
pw = domain.auth_info
xml = domain_transfer_xml({
name: { value: domain.name },
authInfo: { pw: { value: pw } }
}, 'query', {
}, 'request', {
_anonymus: [
legalDocument: {
value: 'dGVzdCBmYWlsCg==',
@ -1331,8 +1440,8 @@ describe 'EPP Domain', epp: true do
it 'returns an error for incorrect op attribute' do
response = epp_plain_request(domain_transfer_xml({}, 'bla'), validate_input: false)
response[:result_code].should == '2306'
response[:msg].should == 'Attribute is invalid: op'
response[:msg].should == 'Parameter value range error: op'
response[:result_code].should == '2004'
end
it 'creates new pw after successful transfer' do
@ -1340,7 +1449,7 @@ describe 'EPP Domain', epp: true do
xml = domain_transfer_xml({
name: { value: domain.name },
authInfo: { pw: { value: pw } }
}, 'query', {
}, 'request', {
_anonymus: [
legalDocument: {
value: 'dGVzdCBmYWlsCg==',
@ -1352,8 +1461,8 @@ describe 'EPP Domain', epp: true do
login_as :registrar2 do
epp_plain_request(xml) # transfer domain
response = epp_plain_request(xml) # attempt second transfer
response[:result_code].should == '2201'
response[:msg].should == 'Authorization error'
response[:result_code].should == '2201'
end
end
@ -1372,10 +1481,118 @@ describe 'EPP Domain', epp: true do
})
response = epp_plain_request(xml)
response[:msg].should == 'Pending transfer was not found'
response[:msg].should == 'No transfers found'
response[:result_code].should == '2303'
end
it 'should not return transfers when there are none' do
xml = domain_transfer_xml({
name: { value: domain.name },
authInfo: { pw: { value: domain.auth_info } }
}, 'query')
response = epp_plain_request(xml)
response[:results][0][:msg].should == 'No transfers found'
response[:results][0][:result_code].should == '2303'
end
it 'should allow querying domain transfer' do
Setting.transfer_wait_time = 1
pw = domain.auth_info
xml = domain_transfer_xml({
name: { value: domain.name },
authInfo: { pw: { value: pw } }
}, 'request', {
_anonymus: [
legalDocument: {
value: 'dGVzdCBmYWlsCg==',
attrs: { type: 'pdf' }
}
]
})
login_as :registrar2 do
response = epp_plain_request(xml)
response[:results][0][:msg].should == 'Command completed successfully'
response[:results][0][:result_code].should == '1000'
trn_data = response[:parsed].css('trnData')
dtl = domain.domain_transfers.last
trn_data.css('name').text.should == domain.name
trn_data.css('trStatus').text.should == 'pending'
trn_data.css('reID').text.should == 'REGDOMAIN2'
trn_data.css('reDate').text.should == dtl.transfer_requested_at.in_time_zone.utc.utc.iso8601
trn_data.css('acDate').text.should == dtl.wait_until.in_time_zone.utc.utc.iso8601
trn_data.css('acID').text.should == 'REGDOMAIN1'
trn_data.css('exDate').text.should == domain.valid_to.in_time_zone.utc.utc.iso8601
xml = domain_transfer_xml({
name: { value: domain.name },
authInfo: { pw: { value: pw } }
}, 'query')
response = epp_plain_request(xml)
response[:results][0][:msg].should == 'Command completed successfully'
response[:results][0][:result_code].should == '1000'
trn_data = response[:parsed].css('trnData')
dtl = domain.domain_transfers.last
trn_data.css('name').text.should == domain.name
trn_data.css('trStatus').text.should == 'pending'
trn_data.css('reID').text.should == 'REGDOMAIN2'
trn_data.css('reDate').text.should == dtl.transfer_requested_at.in_time_zone.utc.utc.iso8601
trn_data.css('acDate').text.should == dtl.wait_until.in_time_zone.utc.utc.iso8601
trn_data.css('acID').text.should == 'REGDOMAIN1'
trn_data.css('exDate').text.should == domain.valid_to.in_time_zone.utc.utc.iso8601
end
# approves pending transfer
xml = domain_transfer_xml({
name: { value: domain.name },
authInfo: { pw: { value: pw } }
}, 'approve', {
_anonymus: [
legalDocument: {
value: 'dGVzdCBmYWlsCg==',
attrs: { type: 'pdf' }
}
]
})
response = epp_plain_request(xml)
response[:results][0][:msg].should == 'Command completed successfully'
response[:results][0][:result_code].should == '1000'
# query should return last completed transfer
domain.reload
pw = domain.auth_info
xml = domain_transfer_xml({
name: { value: domain.name },
authInfo: { pw: { value: pw } }
}, 'query')
response = epp_plain_request(xml)
response[:results][0][:msg].should == 'Command completed successfully'
response[:results][0][:result_code].should == '1000'
trn_data = response[:parsed].css('trnData')
dtl = domain.domain_transfers.last
trn_data.css('name').text.should == domain.name
trn_data.css('trStatus').text.should == 'clientApproved'
trn_data.css('reID').text.should == 'REGDOMAIN2'
trn_data.css('reDate').text.should == dtl.transfer_requested_at.in_time_zone.utc.utc.iso8601
trn_data.css('acDate').text.should == dtl.transferred_at.in_time_zone.utc.utc.iso8601
trn_data.css('acID').text.should == 'REGDOMAIN1'
trn_data.css('exDate').text.should == domain.valid_to.in_time_zone.utc.utc.iso8601
Setting.transfer_wait_time = 0
end
### UPDATE ###
it 'should update right away without update pending status' do
existing_pw = domain.auth_info
@ -1968,6 +2185,9 @@ describe 'EPP Domain', epp: true do
### RENEW ###
it 'renews a domain' do
old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count
domain.valid_to = Time.zone.now.to_date + 10.days
domain.save
@ -1986,6 +2206,109 @@ describe 'EPP Domain', epp: true do
name = response[:parsed].css('renData name').text
ex_date.should == "#{(exp_date + 1.year)}T00:00:00Z"
name.should == domain.name
@registrar1.balance.should == old_balance - 15.0
@registrar1.cash_account.account_activities.count.should == old_activities + 1
a = @registrar1.cash_account.account_activities.last
a.description.should == "Renew #{Domain.last.name}"
a.sum.should == -BigDecimal.new('15.0')
a.activity_type = AccountActivity::RENEW
a.log_pricelist_id.should == @pricelist_renew_1_year.id
end
it 'renews a domain with 2 year period' do
old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count
domain.valid_to = Time.zone.now.to_date + 10.days
domain.save
exp_date = domain.valid_to.to_date
xml = @epp_xml.domain.renew(
name: { value: domain.name },
curExpDate: { value: exp_date.to_s },
period: { value: '730', attrs: { unit: 'd' } }
)
response = epp_plain_request(xml)
response[:results][0][:msg].should == 'Command completed successfully'
response[:results][0][:result_code].should == '1000'
ex_date = response[:parsed].css('renData exDate').text
name = response[:parsed].css('renData name').text
ex_date.should == "#{(exp_date + 2.year)}T00:00:00Z"
name.should == domain.name
@registrar1.balance.should == old_balance - 35.0
@registrar1.cash_account.account_activities.count.should == old_activities + 1
a = @registrar1.cash_account.account_activities.last
a.description.should == "Renew #{Domain.last.name}"
a.sum.should == -BigDecimal.new('35.0')
a.activity_type = AccountActivity::CREATE
end
it 'renews a domain with 3 year period' do
old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count
domain.valid_to = Time.zone.now.to_date + 10.days
domain.save
exp_date = domain.valid_to.to_date
xml = @epp_xml.domain.renew(
name: { value: domain.name },
curExpDate: { value: exp_date.to_s },
period: { value: '36', attrs: { unit: 'm' } }
)
response = epp_plain_request(xml)
response[:results][0][:msg].should == 'Command completed successfully'
response[:results][0][:result_code].should == '1000'
ex_date = response[:parsed].css('renData exDate').text
name = response[:parsed].css('renData name').text
ex_date.should == "#{(exp_date + 3.year)}T00:00:00Z"
name.should == domain.name
@registrar1.balance.should == old_balance - 62.0
@registrar1.cash_account.account_activities.count.should == old_activities + 1
a = @registrar1.cash_account.account_activities.last
a.description.should == "Renew #{Domain.last.name}"
a.sum.should == -BigDecimal.new('62.0')
a.activity_type = AccountActivity::CREATE
end
it 'does not renew a domain if credit balance low' do
f = Fabricate(:pricelist, {
valid_to: Time.zone.now + 1.day,
operation_category: 'renew',
duration: '1year',
price: 100000
})
old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count
domain.valid_to = Time.zone.now.to_date + 10.days
domain.save
exp_date = domain.valid_to.to_date
xml = @epp_xml.domain.renew(
name: { value: domain.name },
curExpDate: { value: exp_date.to_s },
period: { value: '1', attrs: { unit: 'y' } }
)
response = epp_plain_request(xml)
response[:results][0][:msg].should == 'Billing failure - credit balance low'
response[:results][0][:result_code].should == '2104'
domain.reload
domain.valid_to.should == exp_date # ensure domain was not renewed
@registrar1.balance.should == old_balance
@registrar1.cash_account.account_activities.count.should == old_activities
f.delete
end
it 'returns an error when given and current exp dates do not match' do
@ -2088,6 +2411,7 @@ describe 'EPP Domain', epp: true do
end
it 'should renew a expired domain' do
pending("Please inspect, somehow SERVER_HOLD is false and test fails")
domain.valid_to = Time.zone.now - 50.days
new_valid_to = domain.valid_to + 1.year
domain.outzone_at = Time.zone.now - 50.days

View file

@ -10,7 +10,7 @@ describe 'EPP Helper', epp: true do
expected = Nokogiri::XML('<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<transfer op="query">
<transfer op="request">
<domain:transfer
xmlns:domain="https://raw.githubusercontent.com/internetee/registry/alpha/doc/schemas/domain-eis-1.0.xsd">
<domain:name>' + dn + '</domain:name>

View file

@ -121,31 +121,32 @@ describe 'EPP Keyrelay', epp: true do
@registrar2.messages.queued.count.should == msg_count
end
it 'does not allow both relative and absolute' do
msg_count = @registrar2.messages.queued.count
xml = @epp_xml.keyrelay({
name: { value: @domain.name },
keyData: {
flags: { value: '256' },
protocol: { value: '3' },
alg: { value: '8' },
pubKey: { value: 'cmlraXN0aGViZXN0' }
},
authInfo: {
pw: { value: @domain.auth_info }
},
expiry: {
relative: { value: 'P1D' },
absolute: { value: '2014-12-23' }
}
})
# keyrelay not enabled at the moment
# it 'does not allow both relative and absolute' do
# msg_count = @registrar2.messages.queued.count
# xml = @epp_xml.keyrelay({
# name: { value: @domain.name },
# keyData: {
# flags: { value: '256' },
# protocol: { value: '3' },
# alg: { value: '8' },
# pubKey: { value: 'cmlraXN0aGViZXN0' }
# },
# authInfo: {
# pw: { value: @domain.auth_info }
# },
# expiry: {
# relative: { value: 'P1D' },
# absolute: { value: '2014-12-23' }
# }
# })
response = epp_plain_request(xml, :xml)
response[:msg].should == 'Exactly one parameter required: keyrelay > expiry > relative OR '\
'keyrelay > expiry > absolute'
# response = epp_plain_request(xml, :xml)
# response[:msg].should == 'Exactly one parameter required: keyrelay > expiry > relative OR '\
# 'keyrelay > expiry > absolute'
@registrar2.messages.queued.count.should == msg_count
end
# @registrar2.messages.queued.count.should == msg_count
# end
it 'saves legal document with keyrelay' do
xml = @epp_xml.keyrelay({

View file

@ -87,7 +87,8 @@ describe 'EPP Poll', epp: true do
})
response = epp_plain_request(xml, validate_input: false)
response[:msg].should == 'Attribute is invalid: op'
response[:msg].should == 'Parameter value range error: op'
response[:result_code].should == '2004'
end
it 'dequeues multiple messages' do

View file

@ -1,8 +1,8 @@
Fabricator(:pricelist) do
valid_from 1.year.ago
valid_to 1.year.since
category '.ee'
category 'ee'
duration '1year'
operation_category 'new'
operation_category 'create'
price 10
end

View file

@ -1,3 +1,3 @@
Fabricator(:reserved_domain) do
name '1162.ee'
names { { '1162.ee': 'abc' } }
end

View file

@ -3,7 +3,7 @@ require 'rails_helper'
feature 'Invoice', type: :feature do
before :all do
@user = Fabricate(:admin_user)
Fabricate(:invoice)
@invoice = Fabricate(:invoice)
end
before do
@ -12,15 +12,13 @@ feature 'Invoice', type: :feature do
it 'should show index of invoices' do
visit admin_invoices_url
i = Invoice.first
page.should have_link("Invoice no. #{i.id}")
page.should have_link("Invoice no. #{@invoice.id}")
end
it 'should show invoice' do
visit admin_invoices_url
i = Invoice.first
click_link("Invoice no. #{i.id}")
click_link("Invoice no. #{@invoice.id}")
page.should have_content("Seller")
page.should have_content("Details")
page.should have_content("Paldiski mnt. 123")
@ -42,4 +40,23 @@ feature 'Invoice', type: :feature do
page.should have_content('120.0')
page.should have_content(r.name)
end
it 'should forward invoice' do
visit '/admin/invoices'
click_link @invoice.to_s
click_link 'Forward'
click_button 'Forward'
page.should have_text('Failed to forward invoice')
fill_in 'Billing email', with: 'test@test.ee'
click_button 'Forward'
page.should have_text('Invoice forwarded')
end
it 'should download invoice' do
visit '/admin/invoices'
click_link @invoice.to_s
click_link 'Download'
response_headers['Content-Type'].should == 'application/pdf'
response_headers['Content-Disposition'].should == "attachment; filename=\"#{@invoice.pdf_name}\""
end
end

View file

@ -0,0 +1,43 @@
require 'rails_helper'
feature 'ReservedDomain', type: :feature do
before :all do
@user = Fabricate(:admin_user)
end
before do
sign_in @user
end
it 'should manage reserved domains' do
visit admin_reserved_domains_url
page.should have_content('Reserved domains')
d = Fabricate.build(:domain, name: '110.ee')
d.valid?
d.errors.full_messages.should match_array([])
fill_in 'reserved_domains', with: "110.ee: testpw"
click_button 'Save'
page.should have_content('Record updated')
page.should have_content('110.ee: testpw')
d.valid?.should == false
d.errors.full_messages.should match_array(
["Required parameter missing; reserved>pw element required for reserved domains"]
)
d.reserved_pw = 'wrongpw'
d.valid?.should == false
d.reserved_pw = 'testpw'
d.valid?.should == true
d.errors.full_messages.should match_array([])
d.save
visit admin_reserved_domains_url
page.should have_content('110.ee')
page.should_not have_content('110.ee: testpw')
end
end

View file

@ -27,5 +27,12 @@ feature 'Account activity', type: :feature do
current_path.should == '/registrar/account_activities'
page.should have_text('+110.0 EUR')
end
it 'should download csv' do
visit '/registrar/account_activities'
click_link 'Export CSV'
response_headers['Content-Type'].should == 'text/csv'
response_headers['Content-Disposition'].should match(/attachment; filename="account_activities_\d+\.csv"/)
end
end
end

View file

@ -112,4 +112,29 @@ describe DomainMailer do
@mail.body.encoded.should =~ %r{registrant\/domain_delete_con} # somehowe delete_confirms not matching
end
end
describe 'registrant successfully changed confirmation' do
before :all do
@registrant = Fabricate(:registrant, email: 'test@example.com')
@domain = Fabricate(:domain, registrant: @registrant)
@domain.deliver_emails = true
@mail = DomainMailer.registrant_updated(@domain)
end
it 'should render email subject' do
@mail.subject.should =~ /registreerija vahetus teostatud/
end
it 'should have sender email' do
@mail.from.should == ["noreply@internet.ee"]
end
it 'should send to registrant email' do
@mail.to.should == ["test@example.com"]
end
it 'should render body' do
@mail.body.encoded.should =~ /registreerija vahetuse taotlus on kinnitatud/
end
end
end

View file

@ -62,6 +62,11 @@ describe BankStatement do
AccountActivity.count.should == 1
a = AccountActivity.last
a.description.should == "Invoice no. #{invoice.number}"
a.sum.should == BigDecimal.new('200.0')
a.activity_type = AccountActivity::ADD_CREDIT
r.cash_account.balance.should == 200.0
bs.bank_transactions.unbinded.count.should == 1

View file

@ -94,6 +94,30 @@ describe Domain do
@domain.registrant_update_confirmable?('123').should == false
end
it 'should not find any domain pendings to clean' do
Domain.clean_expired_pendings.should == 0
end
it 'should not find any domains with wrong pendings' do
domain = Fabricate(:domain)
domain.registrant_verification_asked!('frame-str', '1')
domain.registrant_verification_asked_at = 30.days.ago
domain.save
Domain.clean_expired_pendings.should == 0
end
it 'should clean domain pendings' do
domain = Fabricate(:domain)
domain.registrant_verification_asked!('frame-str', '1')
domain.registrant_verification_asked_at = 30.days.ago
domain.pending_delete!
Domain.clean_expired_pendings.should == 1
domain.reload.pending_delete?.should == false
domain.pending_json.should == {}
end
it 'should expire domains' do
Domain.start_expire_period
@domain.statuses.include?(DomainStatus::EXPIRED).should == false
@ -182,6 +206,128 @@ describe Domain do
@domain.force_delete_at.should be_nil
end
it 'should set expired status and update outzone_at and delete_at' do
domain = Fabricate(:domain)
domain.statuses.should == ['ok']
domain.set_expired
domain.changes.keys.should == ['statuses', 'outzone_at', 'delete_at']
domain.save
domain.statuses.should == ['expired']
end
it 'should know its create price' do
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '1year',
price: 1.50,
valid_from: Time.zone.parse('2015-01-01'),
valid_to: nil
})
domain = Fabricate(:domain)
domain.pricelist('create').price.amount.should == 1.50
domain = Fabricate(:domain, period: 12, period_unit: 'm')
domain.pricelist('create').price.amount.should == 1.50
domain = Fabricate(:domain, period: 365, period_unit: 'd')
domain.pricelist('create').price.amount.should == 1.50
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '2years',
price: 3,
valid_from: Time.zone.parse('2015-01-01'),
valid_to: nil
})
domain = Fabricate(:domain, period: 2)
domain.pricelist('create').price.amount.should == 3.0
domain = Fabricate(:domain, period: 24, period_unit: 'm')
domain.pricelist('create').price.amount.should == 3.0
domain = Fabricate(:domain, period: 730, period_unit: 'd')
domain.pricelist('create').price.amount.should == 3.0
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '3years',
price: 6,
valid_from: Time.zone.parse('2015-01-01'),
valid_to: nil
})
domain = Fabricate(:domain, period: 3)
domain.pricelist('create').price.amount.should == 6.0
domain = Fabricate(:domain, period: 36, period_unit: 'm')
domain.pricelist('create').price.amount.should == 6.0
domain = Fabricate(:domain, period: 1095, period_unit: 'd')
domain.pricelist('create').price.amount.should == 6.0
end
it 'should know its renew price' do
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'renew',
duration: '1year',
price: 1.30,
valid_from: Time.zone.parse('2015-01-01'),
valid_to: nil
})
domain = Fabricate(:domain)
domain.pricelist('renew').price.amount.should == 1.30
domain = Fabricate(:domain, period: 12, period_unit: 'm')
domain.pricelist('renew').price.amount.should == 1.30
domain = Fabricate(:domain, period: 365, period_unit: 'd')
domain.pricelist('renew').price.amount.should == 1.30
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'renew',
duration: '2years',
price: 3.1,
valid_from: Time.zone.parse('2015-01-01'),
valid_to: nil
})
domain = Fabricate(:domain, period: 2)
domain.pricelist('renew').price.amount.should == 3.1
domain = Fabricate(:domain, period: 24, period_unit: 'm')
domain.pricelist('renew').price.amount.should == 3.1
domain = Fabricate(:domain, period: 730, period_unit: 'd')
domain.pricelist('renew').price.amount.should == 3.1
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'renew',
duration: '3years',
price: 6.1,
valid_from: Time.zone.parse('2015-01-01'),
valid_to: nil
})
domain = Fabricate(:domain, period: 3)
domain.pricelist('renew').price.amount.should == 6.1
domain = Fabricate(:domain, period: 36, period_unit: 'm')
domain.pricelist('renew').price.amount.should == 6.1
domain = Fabricate(:domain, period: 1095, period_unit: 'd')
domain.pricelist('renew').price.amount.should == 6.1
end
context 'about registrant update confirm' do
before :all do
@domain.registrant_verification_token = 123

View file

@ -36,7 +36,6 @@ describe Pricelist do
it 'should not have name' do
@pricelist.name.should == ' '
end
end
context 'with valid attributes' do
@ -56,7 +55,7 @@ describe Pricelist do
end
it 'should have name' do
@pricelist.name.should == 'new .ee'
@pricelist.name.should == 'create ee'
end
it 'should have one version' do
@ -69,4 +68,107 @@ describe Pricelist do
end
end
end
it 'should return correct price' do
Pricelist.pricelist_for('ee', 'create', '1year').should == nil
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '1year',
price: 1.50,
valid_from: Time.zone.parse('2198-01-01'),
valid_to: Time.zone.parse('2199-01-01')
})
Pricelist.pricelist_for('ee', 'create', '1year').should == nil
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '1year',
price: 1.50,
valid_from: Time.zone.parse('2015-01-01'),
valid_to: nil
})
Pricelist.pricelist_for('ee', 'create', '1year').price.amount.should == 1.50
Fabricate(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '1year',
price: 1.30,
valid_from: Time.zone.parse('2015-01-01'),
valid_to: Time.zone.parse('2999-01-01')
})
Pricelist.pricelist_for('ee', 'create', '1year').price.amount.should == 1.30
Fabricate.create(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '1year',
price: 1.20,
valid_from: Time.zone.parse('2015-06-01'),
valid_to: Time.zone.parse('2999-01-01')
})
Pricelist.pricelist_for('ee', 'create', '1year').price.amount.should == 1.20
Fabricate.create(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '1year',
price: 1.10,
valid_from: Time.zone.parse('2014-01-01'),
valid_to: Time.zone.parse('2999-01-01')
})
Pricelist.pricelist_for('ee', 'create', '1year').price.amount.should == 1.20
Fabricate.create(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '1year',
price: 1.10,
valid_from: Time.zone.parse('2999-02-01'),
valid_to: Time.zone.parse('2999-01-01')
})
Pricelist.pricelist_for('ee', 'create', '1year').price.amount.should == 1.20
Fabricate.create(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '1year',
price: 1.10,
valid_from: Time.zone.parse('2015-06-02'),
valid_to: nil
})
Pricelist.pricelist_for('ee', 'create', '1year').price.amount.should == 1.20
Fabricate.create(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '1year',
price: 1.10,
valid_from: Time.zone.parse('2015-07-01'),
valid_to: Time.zone.parse('2999-01-01')
})
Pricelist.pricelist_for('ee', 'create', '1year').price.amount.should == 1.10
Fabricate.create(:pricelist, {
category: 'ee',
operation_category: 'create',
duration: '2years',
price: 1.20,
valid_from: Time.zone.parse('2015-07-01'),
valid_to: Time.zone.parse('2999-01-01')
})
Pricelist.pricelist_for('ee', 'create', '2years').price.amount.should == 1.20
end
end

View file

@ -144,5 +144,22 @@ describe Registrar do
it 'should not have priv contacts' do
@registrar.priv_contacts.size.should == 0
end
it 'should credit and debit registrar cash account' do
@registrar.credit!({ sum: 13.32, description: 'Add money' })
@registrar.balance.should == BigDecimal.new('13.32')
@registrar.cash_account.account_activities.count.should == 1
a = @registrar.cash_account.account_activities.last
a.description.should == 'Add money'
a.sum.should == BigDecimal.new('13.32')
a.log_pricelist_id.should == nil
@registrar.debit!({ sum: 10.31, description: 'Remove money' })
@registrar.balance.should == BigDecimal.new('3.01')
@registrar.cash_account.account_activities.count.should == 2
a = @registrar.cash_account.account_activities.last
a.description.should == 'Remove money'
a.sum.should == -BigDecimal.new('10.31')
end
end
end

View file

@ -144,7 +144,7 @@ module Epp
end
# rubocop: disable Metrics/MethodLength
def domain_create_xml(xml_params = {}, dnssec_params = {})
def domain_create_xml(xml_params = {}, dnssec_params = {}, custom_params = {})
defaults = {
name: { value: next_domain_name },
period: { value: '1', attrs: { unit: 'y' } },
@ -185,7 +185,7 @@ module Epp
dnssec_params = dnssec_defaults.deep_merge(dnssec_params) if dnssec_params != false
custom_params = {
custom_defaults = {
_anonymus: [
legalDocument: {
value: 'dGVzdCBmYWlsCg==',
@ -194,6 +194,8 @@ module Epp
]
}
custom_params = custom_defaults.deep_merge(custom_params) if custom_params != false
epp_xml = EppXml::Domain.new(cl_trid: 'ABC-12345')
epp_xml.create(xml_params, dnssec_params, custom_params)
end
@ -347,7 +349,7 @@ module Epp
epp_xml.check(xml_params)
end
def domain_transfer_xml(xml_params = {}, op = 'query', custom_params = {})
def domain_transfer_xml(xml_params = {}, op = 'request', custom_params = {})
defaults = {
name: { value: next_domain_name },
authInfo: {