Merge branch 'master' into alpha

This commit is contained in:
Priit Tark 2015-07-22 14:30:55 +03:00
commit 676477307d
88 changed files with 3231 additions and 1486 deletions

1
.gitignore vendored
View file

@ -9,6 +9,7 @@ capybara-*.html
/spec/tmp /spec/tmp
**.orig **.orig
config/initializers/secret_token.rb config/initializers/secret_token.rb
config/deploy.rb
config/secrets.yml config/secrets.yml
config/database.yml config/database.yml
/export /export

View file

@ -4,6 +4,7 @@ AllCops:
Exclude: Exclude:
- 'Guardfile' - 'Guardfile'
# stuff generated by AR and rails # stuff generated by AR and rails
- 'config/deploy-example.rb'
- 'db/schema.rb' - 'db/schema.rb'
- 'db/schema-read-only.rb' - 'db/schema-read-only.rb'
- 'db/whois_schema.rb' - 'db/whois_schema.rb'

View file

@ -1,3 +1,12 @@
21.07.2015
* Possible to define custom trusted proxies at application.yml
20.07.2015
* New syntax for setting webclient IP-s (see config/application-example.yml)
* Example mina/deploy.rb renamed to mina/deploy-example.rb in order to not overwrite local deploy scripts
14.07.2015 14.07.2015
* Updated que init script doc example, now status and stop works faster * Updated que init script doc example, now status and stop works faster

View file

@ -5,10 +5,16 @@ module Repp
http_basic do |username, password| http_basic do |username, password|
@current_user ||= ApiUser.find_by(username: username, password: password) @current_user ||= ApiUser.find_by(username: username, password: password)
if @current_user
true
else
error! I18n.t('api_user_not_found'), 401
end
end end
before do before do
if request.ip != ENV['webclient_ip'] webclient_request = ENV['webclient_ips'].split(',').map(&:strip).include?(request.ip)
unless webclient_request
error! I18n.t('ip_is_not_whitelisted'), 401 unless @current_user.registrar.api_ip_white?(request.ip) error! I18n.t('ip_is_not_whitelisted'), 401 unless @current_user.registrar.api_ip_white?(request.ip)
end end
@ -20,7 +26,7 @@ module Repp
message = 'Certificate mismatch! Cert common name should be:' message = 'Certificate mismatch! Cert common name should be:'
request_name = env['HTTP_SSL_CLIENT_S_DN_CN'] request_name = env['HTTP_SSL_CLIENT_S_DN_CN']
if request.ip == ENV['webclient_ip'] if webclient_request
webclient_cert_name = ENV['webclient_cert_common_name'] || 'webclient' webclient_cert_name = ENV['webclient_cert_common_name'] || 'webclient'
error! "Webclient #{message} #{webclient_cert_name}", 401 if webclient_cert_name != request_name error! "Webclient #{message} #{webclient_cert_name}", 401 if webclient_cert_name != request_name
else else

View file

@ -62,3 +62,6 @@ body > .container
border: 1px solid #dddddd border: 1px solid #dddddd
padding-left: 4px padding-left: 4px
padding-right: 4px padding-right: 4px
.disabled-value
padding-top: 8px

View file

@ -16,7 +16,18 @@ class Admin::BankStatementsController < AdminController
end end
def new def new
@bank_statement = BankStatement.new @bank_statement = BankStatement.new(
bank_code: Setting.registry_bank_code,
iban: Setting.registry_iban
)
@invoice = Invoice.find_by(id: params[:invoice_id])
@bank_transaction = @bank_statement.bank_transactions.build(
description: @invoice.to_s,
sum: @invoice.sum,
reference_no: @invoice.reference_no,
paid_at: Time.zone.now.to_date,
currency: 'EUR'
) if @invoice
end end
def create def create
@ -69,6 +80,8 @@ class Admin::BankStatementsController < AdminController
end end
def bank_statement_params def bank_statement_params
params.require(:bank_statement).permit(:th6_file, :bank_code, :iban) params.require(:bank_statement).permit(:th6_file, :bank_code, :iban, bank_transactions_attributes: [
:description, :sum, :currency, :reference_no, :paid_at
])
end end
end end

View file

@ -11,9 +11,38 @@ class Admin::ContactsController < AdminController
render json: Contact.search_by_query(params[:q]) render json: Contact.search_by_query(params[:q])
end end
def edit
end
def update
cp = ignore_empty_statuses
if @contact.update(cp)
flash[:notice] = I18n.t('contact_updated')
redirect_to [:admin, @contact]
else
flash.now[:alert] = I18n.t('failed_to_update_contact')
render 'edit'
end
end
private private
def set_contact def set_contact
@contact = Contact.includes(domains: :registrar).find(params[:id]) @contact = Contact.includes(domains: :registrar).find(params[:id])
end end
def contact_params
if params[:contact]
params.require(:contact).permit({ statuses: [], status_notes_array: [] })
else
{ statuses: [] }
end
end
def ignore_empty_statuses
dp = contact_params
dp[:statuses].reject!(&:blank?)
dp
end
end end

View file

@ -94,12 +94,26 @@ class Epp::ContactsController < EppController
'postalInfo > addr > pc', 'postalInfo > addr > cc', 'voice', 'email' 'postalInfo > addr > pc', 'postalInfo > addr > cc', 'voice', 'email'
) )
ident = params[:parsed_frame].css('ident') ident = params[:parsed_frame].css('ident')
if ident.present? && ident.attr('type').blank?
epp_errors << {
code: '2003',
msg: I18n.t('errors.messages.required_ident_attribute_missing', key: 'type')
}
end
if ident.present? && ident.text != 'birthday' && ident.attr('cc').blank? if ident.present? && ident.text != 'birthday' && ident.attr('cc').blank?
epp_errors << { epp_errors << {
code: '2003', code: '2003',
msg: I18n.t('errors.messages.required_attribute_missing', key: 'ident country code missing') msg: I18n.t('errors.messages.required_ident_attribute_missing', key: 'cc')
} }
end end
# if ident.present? && ident.attr('cc').blank?
# epp_errors << {
# code: '2003',
# msg: I18n.t('errors.messages.required_ident_attribute_missing', key: 'cc')
# }
# end
contact_org_disabled contact_org_disabled
fax_disabled fax_disabled
status_editing_disabled status_editing_disabled

View file

@ -25,6 +25,7 @@ class Epp::DomainsController < EppController
@domain = Epp::Domain.new_from_epp(params[:parsed_frame], current_user) @domain = Epp::Domain.new_from_epp(params[:parsed_frame], current_user)
handle_errors(@domain) and return if @domain.errors.any? handle_errors(@domain) and return if @domain.errors.any?
@domain.valid? @domain.valid?
@domain.errors.delete(:name_dirty) if @domain.errors[:puny_label].any?
handle_errors(@domain) and return if @domain.errors.any? handle_errors(@domain) and return if @domain.errors.any?
handle_errors and return unless balance_ok?('create') handle_errors and return unless balance_ok?('create')
@ -94,8 +95,9 @@ class Epp::DomainsController < EppController
def renew def renew
authorize! :renew, @domain authorize! :renew, @domain
period = params[:parsed_frame].css('period').text period_element = params[:parsed_frame].css('period').text
period_unit = params[:parsed_frame].css('period').first['unit'] period = (period_element.to_i == 0) ? 1 : period_element.to_i
period_unit = Epp::Domain.parse_period_unit_from_frame(params[:parsed_frame]) || 'y'
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
success = @domain.renew( success = @domain.renew(
@ -129,10 +131,14 @@ class Epp::DomainsController < EppController
@domain_transfer = @domain.transfer(params[:parsed_frame], action, current_user) @domain_transfer = @domain.transfer(params[:parsed_frame], action, current_user)
if @domain.errors.empty? && @domain_transfer if @domain_transfer
render_epp_response '/epp/domains/transfer' render_epp_response '/epp/domains/transfer'
else else
handle_errors(@domain) epp_errors << {
code: '2303',
msg: I18n.t('no_transfers_found')
}
handle_errors
end end
end end
@ -154,6 +160,8 @@ class Epp::DomainsController < EppController
@prefix = nil @prefix = nil
requires 'extension > extdata > legalDocument' requires 'extension > extdata > legalDocument'
optional_attribute 'period', 'unit', values: %w(d m y)
status_editing_disabled status_editing_disabled
end end
@ -182,7 +190,9 @@ class Epp::DomainsController < EppController
def validate_renew def validate_renew
@prefix = 'renew > renew >' @prefix = 'renew > renew >'
requires 'name', 'curExpDate', 'period' requires 'name', 'curExpDate'
optional_attribute 'period', 'unit', values: %w(d m y)
end end
def validate_transfer def validate_transfer

View file

@ -13,46 +13,71 @@ class Epp::SessionsController < EppController
success = true success = true
@api_user = ApiUser.find_by(login_params) @api_user = ApiUser.find_by(login_params)
if request.ip == ENV['webclient_ip'] && !Rails.env.test? && !Rails.env.development? webclient_request = ENV['webclient_ips'].split(',').map(&:strip).include?(request.ip)
if webclient_request && !Rails.env.test? && !Rails.env.development?
client_md5 = Certificate.parse_md_from_string(request.env['HTTP_SSL_CLIENT_CERT']) 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'])) server_md5 = Certificate.parse_md_from_string(File.read(ENV['cert_path']))
if client_md5 != server_md5 if client_md5 != server_md5
@msg = 'Authentication error; server closing connection (certificate is not valid)' epp_errors << {
msg: 'Authentication error; server closing connection (certificate is not valid)',
code: '2501'
}
success = false success = false
end end
end end
if request.ip != ENV['webclient_ip'] && @api_user if !webclient_request && @api_user
unless @api_user.api_pki_ok?(request.env['HTTP_SSL_CLIENT_CERT'], request.env['HTTP_SSL_CLIENT_S_DN_CN']) 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)' epp_errors << {
msg: 'Authentication error; server closing connection (certificate is not valid)',
code: '2501'
}
success = false success = false
end end
end end
if success && !@api_user if success && !@api_user
@msg = 'Authentication error; server closing connection (API user not found)' epp_errors << {
msg: 'Authentication error; server closing connection (API user not found)',
code: '2501'
}
success = false success = false
end end
if success && !@api_user.try(:active) if success && !@api_user.try(:active)
@msg = 'Authentication error; server closing connection (API user is not active)' epp_errors << {
msg: 'Authentication error; server closing connection (API user is not active)',
code: '2501'
}
success = false success = false
end end
if success && !ip_white? if success && !ip_white?
@msg = 'Authentication error; server closing connection (IP is not whitelisted)' epp_errors << {
msg: 'Authentication error; server closing connection (IP is not whitelisted)',
code: '2501'
}
success = false success = false
end end
if success && !connection_limit_ok? if success && !connection_limit_ok?
@msg = 'Authentication error; server closing connection (connection limit reached)' epp_errors << {
msg: 'Authentication error; server closing connection (connection limit reached)',
code: '2501'
}
success = false success = false
end end
if success if success
if parsed_frame.css('newPW').first if parsed_frame.css('newPW').first
unless @api_user.update(password: parsed_frame.css('newPW').first.text) unless @api_user.update(password: parsed_frame.css('newPW').first.text)
response.headers['X-EPP-Returncode'] = '2200' response.headers['X-EPP-Returncode'] = '2500'
handle_errors(@api_user) and return handle_errors(@api_user) and return
end end
end end
@ -61,8 +86,8 @@ class Epp::SessionsController < EppController
epp_session.update_column(:registrar_id, @api_user.registrar_id) epp_session.update_column(:registrar_id, @api_user.registrar_id)
render_epp_response('login_success') render_epp_response('login_success')
else else
response.headers['X-EPP-Returncode'] = '2200' response.headers['X-EPP-Returncode'] = '2500'
render_epp_response('login_fail') handle_errors
end end
end end
# rubocop: enable Metrics/MethodLength # rubocop: enable Metrics/MethodLength
@ -71,7 +96,8 @@ class Epp::SessionsController < EppController
# rubocop: enable Metrics/CyclomaticComplexity # rubocop: enable Metrics/CyclomaticComplexity
def ip_white? def ip_white?
return true if request.ip == ENV['webclient_ip'] webclient_request = ENV['webclient_ips'].split(',').map(&:strip).include?(request.ip)
return true if webclient_request
if @api_user if @api_user
return false unless @api_user.registrar.api_ip_white?(request.ip) return false unless @api_user.registrar.api_ip_white?(request.ip)
end end

View file

@ -8,6 +8,18 @@ class EppController < ApplicationController
before_action :latin_only before_action :latin_only
before_action :validate_request before_action :validate_request
before_action :update_epp_session before_action :update_epp_session
around_action :catch_epp_errors
def catch_epp_errors
err = catch(:epp_error) do
yield
nil
end
return unless err
@errors = [err]
handle_errors
end
helper_method :current_user helper_method :current_user
rescue_from StandardError do |e| rescue_from StandardError do |e|
@ -28,9 +40,18 @@ class EppController < ApplicationController
}] }]
end end
logger.error e.message if Rails.env.test? || Rails.env.development?
logger.error e.backtrace.join("\n") # rubocop:disable Rails/Output
# TODO: NOITFY AIRBRAKE / ERRBIT HERE puts e.backtrace.reverse.join("\n")
puts "\nFROM-EPP-RESCUE: #{e.message}\n"
# rubocop:enable Rails/Output
else
logger.error "FROM-EPP-RESCUE: #{e.message}"
logger.error e.backtrace.join("\n")
# TODO: NOITFY AIRBRAKE / ERRBIT HERE
NewRelic::Agent.notice_error(e)
end
end end
render_epp_response '/epp/error' render_epp_response '/epp/error'
@ -102,7 +123,7 @@ class EppController < ApplicationController
msg: 'handle_errors was executed when there were actually no errors' msg: 'handle_errors was executed when there were actually no errors'
} }
# rubocop:disable Rails/Output # rubocop:disable Rails/Output
puts obj.errors.full_messages if Rails.env.test? puts "FULL MESSAGE: #{obj.errors.full_messages} #{obj.errors.inspect}" if Rails.env.test?
# rubocop: enable Rails/Output # rubocop: enable Rails/Output
end end
@ -125,8 +146,13 @@ class EppController < ApplicationController
def latin_only def latin_only
return true if params['frame'].blank? return true if params['frame'].blank?
return true if params['frame'].match(/\A[\p{Latin}\p{Z}\p{P}\p{S}\p{Cc}\p{Cf}\w_\'\+\-\.\(\)\/]*\Z/i) return true if params['frame'].match(/\A[\p{Latin}\p{Z}\p{P}\p{S}\p{Cc}\p{Cf}\w_\'\+\-\.\(\)\/]*\Z/i)
render_epp_response '/epp/latin_error'
false epp_errors << {
msg: 'Parameter value policy error. Allowed only Latin characters.',
code: '2306'
}
handle_errors and return false
end end
# VALIDATION # VALIDATION
@ -212,11 +238,11 @@ class EppController < ApplicationController
end end
def optional_attribute(element_selector, attribute_selector, options) def optional_attribute(element_selector, attribute_selector, options)
element = requires(element_selector, allow_blank: options[:allow_blank]) full_selector = [@prefix, element_selector].compact.join(' ')
element = params[:parsed_frame].css(full_selector).first
return unless element return unless element
attribute = element[attribute_selector] attribute = element[attribute_selector]
return if (attribute && options[:values].include?(attribute)) || !attribute return if (attribute && options[:values].include?(attribute)) || !attribute
epp_errors << { epp_errors << {

View file

@ -1,4 +1,25 @@
class ApplicationMailer < ActionMailer::Base class ApplicationMailer < ActionMailer::Base
default from: 'noreply@internet.ee' default from: 'noreply@internet.ee'
layout 'mailer' layout 'mailer'
def whitelist_blocked?(emails)
return false if Rails.env.production? || Rails.env.test?
emails = [emails] unless emails.is_a?(Array)
emails = emails.flatten
emails.each do |email|
next unless TEST_EMAILS.include?(email)
logger.warn "EMAIL SENDING WAS BLOCKED BY WHITELIST: #{email}"
return true
end
false
end
# turn on delivery on specific (epp) request only, thus rake tasks does not deliver anything
def delivery_off?(model)
return false if model.deliver_emails == true
logger.warn "EMAIL SENDING WAS NOT ACTIVATED " \
"BY MODEL OBJECT: id ##{model.try(:id)} deliver_emails returned false"
true
end
end end

View file

@ -1,23 +1,34 @@
class ContactMailer < ApplicationMailer class ContactMailer < ApplicationMailer
# rubocop: disable Metrics/CyclomaticComplexity # rubocop:disable Metrics/MethodLength
def email_updated(contact) def email_updated(contact)
unless Rails.env.production? return if delivery_off?(contact)
return unless TEST_EMAILS.include?(contact.email) || TEST_EMAILS.include?(contact.email_was)
end
# turn on delivery on specific request only, thus rake tasks does not deliver anything
return if contact.deliver_emails != true
@contact = contact @contact = contact
emails = [] emails = []
emails << [@contact.email, @contact.email_was] if @contact.registrant_domains.present? emails << [@contact.email, @contact.email_was] if @contact.registrant_domains.present?
emails << @contact.domains.map(&:registrant_email) if @contact.domains.present? emails << @contact.domains.map(&:registrant_email) if @contact.domains.present?
emails = emails.uniq emails = emails.uniq
return if whitelist_blocked?(emails)
emails.each do |email| emails.each do |email|
mail(to: email, subject: "#{I18n.t(:contact_email_update_subject)} [#{@contact.code}]") begin
mail(to: email, subject: "#{I18n.t(:contact_email_update_subject)} [#{@contact.code}]")
rescue EOFError,
IOError,
TimeoutError,
Errno::ECONNRESET,
Errno::ECONNABORTED,
Errno::EPIPE,
Errno::ETIMEDOUT,
Net::SMTPAuthenticationError,
Net::SMTPServerBusy,
Net::SMTPFatalError,
Net::SMTPSyntaxError,
Net::SMTPUnknownError,
OpenSSL::SSL::SSLError => e
logger.warn "EMAIL SENDING FAILED: #{email}: #{e}"
end
end end
end end
# rubocop: enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/MethodLength
end end

View file

@ -1,10 +1,7 @@
class DomainMailer < ApplicationMailer class DomainMailer < ApplicationMailer
def registrant_pending_updated(domain) def registrant_pending_updated(domain)
@domain = domain @domain = domain
return if Rails.env.production? ? false : !TEST_EMAILS.include?(@domain.registrant_email) return if delivery_off?(@domain)
# 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? if @domain.registrant_verification_token.blank?
logger.warn "EMAIL NOT DELIVERED: registrant_verification_token is missing for #{@domain.name}" logger.warn "EMAIL NOT DELIVERED: registrant_verification_token is missing for #{@domain.name}"
@ -21,27 +18,23 @@ class DomainMailer < ApplicationMailer
confirm_path = "#{ENV['registrant_url']}/registrant/domain_update_confirms" confirm_path = "#{ENV['registrant_url']}/registrant/domain_update_confirms"
@verification_url = "#{confirm_path}/#{@domain.id}?token=#{@domain.registrant_verification_token}" @verification_url = "#{confirm_path}/#{@domain.id}?token=#{@domain.registrant_verification_token}"
return if whitelist_blocked?(@old_registrant.email)
mail(to: @old_registrant.email, mail(to: @old_registrant.email,
subject: "#{I18n.t(:domain_registrant_pending_updated_subject, name: @domain.name)} [#{@domain.name}]") subject: "#{I18n.t(:domain_registrant_pending_updated_subject, name: @domain.name)} [#{@domain.name}]")
end end
def registrant_updated(domain) def registrant_updated(domain)
@domain = domain @domain = domain
return if Rails.env.production? ? false : !TEST_EMAILS.include?(@domain.registrant_email) return if delivery_off?(@domain)
# turn on delivery on specific EPP request only, thus rake tasks does not deliver anything
return if @domain.deliver_emails != true
return if whitelist_blocked?(@domain.registrant_email)
mail(to: @domain.registrant_email, mail(to: @domain.registrant_email,
subject: "#{I18n.t(:domain_registrant_updated, name: @domain.name)} [#{@domain.name}]") subject: "#{I18n.t(:domain_registrant_updated, name: @domain.name)} [#{@domain.name}]")
end end
def pending_deleted(domain) def pending_deleted(domain)
@domain = domain @domain = domain
return if Rails.env.production? ? false : !TEST_EMAILS.include?(@domain.registrant_email) return if delivery_off?(@domain)
# 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? if @domain.registrant_verification_token.blank?
logger.warn "EMAIL NOT DELIVERED: registrant_verification_token is missing for #{@domain.name}" logger.warn "EMAIL NOT DELIVERED: registrant_verification_token is missing for #{@domain.name}"
@ -58,6 +51,7 @@ class DomainMailer < ApplicationMailer
confirm_path = "#{ENV['registrant_url']}/registrant/domain_delete_confirms" confirm_path = "#{ENV['registrant_url']}/registrant/domain_delete_confirms"
@verification_url = "#{confirm_path}/#{@domain.id}?token=#{@domain.registrant_verification_token}" @verification_url = "#{confirm_path}/#{@domain.id}?token=#{@domain.registrant_verification_token}"
return if whitelist_blocked?(@old_registrant.email)
mail(to: @old_registrant.email, mail(to: @old_registrant.email,
subject: "#{I18n.t(:domain_pending_deleted_subject, name: @domain.name)} [#{@domain.name}]") subject: "#{I18n.t(:domain_pending_deleted_subject, name: @domain.name)} [#{@domain.name}]")
end end

View file

@ -1,6 +1,6 @@
class InvoiceMailer < ApplicationMailer class InvoiceMailer < ApplicationMailer
def invoice_email(invoice, pdf) def invoice_email(invoice, pdf)
return if Rails.env.production? ? false : !TEST_EMAILS.include?(invoice.billing_email) return if whitelist_blocked?(invoice.billing_email)
@invoice = invoice @invoice = invoice
attachments[invoice.pdf_name] = pdf attachments[invoice.pdf_name] = pdf

View file

@ -2,6 +2,8 @@ class BankStatement < ActiveRecord::Base
include Versions include Versions
has_many :bank_transactions has_many :bank_transactions
accepts_nested_attributes_for :bank_transactions
attr_accessor :th6_file attr_accessor :th6_file
validates :bank_code, :iban, presence: true validates :bank_code, :iban, presence: true

View file

@ -141,7 +141,7 @@ class Certificate < ActiveRecord::Base
end end
def update_id_crl def update_id_crl
STDOUT << "#{Time.zone.now.utc} - Updating ID CRL\n" STDOUT << "#{Time.zone.now.utc} - Updating ID CRL\n" unless Rails.env.test?
_out, _err, _st = Open3.capture3(" _out, _err, _st = Open3.capture3("
mkdir -p #{ENV['crl_dir']}/crl-id-temp mkdir -p #{ENV['crl_dir']}/crl-id-temp
@ -169,11 +169,11 @@ class Certificate < ActiveRecord::Base
rm -rf #{ENV['crl_dir']}/crl-id-temp rm -rf #{ENV['crl_dir']}/crl-id-temp
") ")
STDOUT << "#{Time.zone.now.utc} - ID CRL updated\n" STDOUT << "#{Time.zone.now.utc} - ID CRL updated\n" unless Rails.env.test?
end end
def update_registry_crl def update_registry_crl
STDOUT << "#{Time.zone.now.utc} - Updating registry CRL\n" STDOUT << "#{Time.zone.now.utc} - Updating registry CRL\n" unless Rails.env.test?
_out, _err, _st = Open3.capture3(" _out, _err, _st = Open3.capture3("
mkdir -p #{ENV['crl_dir']}/crl-temp mkdir -p #{ENV['crl_dir']}/crl-temp
@ -192,13 +192,13 @@ class Certificate < ActiveRecord::Base
rm -rf #{ENV['crl_dir']}/crl-temp rm -rf #{ENV['crl_dir']}/crl-temp
") ")
STDOUT << "#{Time.zone.now.utc} - Registry CRL updated\n" STDOUT << "#{Time.zone.now.utc} - Registry CRL updated\n" unless Rails.env.test?
end end
def reload_apache def reload_apache
STDOUT << "#{Time.zone.now.utc} - Reloading apache\n" STDOUT << "#{Time.zone.now.utc} - Reloading apache\n" unless Rails.env.test?
_out, _err, _st = Open3.capture3("sudo /etc/init.d/apache2 reload") _out, _err, _st = Open3.capture3("sudo /etc/init.d/apache2 reload")
STDOUT << "#{Time.zone.now.utc} - Apache reloaded\n" STDOUT << "#{Time.zone.now.utc} - Apache reloaded\n" unless Rails.env.test?
end end
def parse_md_from_string(crt) def parse_md_from_string(crt)

View file

@ -5,10 +5,12 @@ class Contact < ActiveRecord::Base
belongs_to :registrar belongs_to :registrar
has_many :domain_contacts has_many :domain_contacts
has_many :domains, through: :domain_contacts has_many :domains, through: :domain_contacts
has_many :statuses, class_name: 'ContactStatus', dependent: :destroy
has_many :legal_documents, as: :documentable has_many :legal_documents, as: :documentable
has_many :registrant_domains, class_name: 'Domain', foreign_key: 'registrant_id' # when contant is registrant has_many :registrant_domains, class_name: 'Domain', foreign_key: 'registrant_id' # when contant is registrant
# TODO: remove later
has_many :depricated_statuses, class_name: 'DepricatedContactStatus', dependent: :destroy
accepts_nested_attributes_for :legal_documents accepts_nested_attributes_for :legal_documents
validates :name, :phone, :email, :ident, :ident_type, validates :name, :phone, :email, :ident, :ident_type,
@ -23,9 +25,15 @@ class Contact < ActiveRecord::Base
validates :ident_country_code, presence: true, if: proc { |c| %w(bic priv).include? c.ident_type } validates :ident_country_code, presence: true, if: proc { |c| %w(bic priv).include? c.ident_type }
validates :code, validates :code,
uniqueness: { message: :epp_id_taken }, uniqueness: { message: :epp_id_taken },
format: { with: /\A[\w\-\:]*\Z/i }, format: { with: /\A[\w\-\:]*\Z/i, message: :invalid },
length: { maximum: 100 } length: { maximum: 100, message: :too_long_contact_code }
validate :ident_valid_format? validate :ident_valid_format?
validate :uniq_statuses?
after_initialize do
self.statuses = [] if statuses.nil?
self.status_notes = {} if status_notes.nil?
end
before_validation :set_ident_country_code before_validation :set_ident_country_code
before_validation :prefix_code before_validation :prefix_code
@ -37,10 +45,10 @@ class Contact < ActiveRecord::Base
ContactMailer.email_updated(self).deliver_now ContactMailer.email_updated(self).deliver_now
end end
after_save :manage_statuses before_save :manage_statuses
def manage_statuses def manage_statuses
ContactStatus.manage(statuses, self) manage_linked
statuses.reload manage_ok
end end
scope :current_registrars, ->(id) { where(registrar_id: id) } scope :current_registrars, ->(id) { where(registrar_id: id) }
@ -58,6 +66,79 @@ class Contact < ActiveRecord::Base
attr_accessor :deliver_emails attr_accessor :deliver_emails
#
# STATUSES
#
# Requests to delete the object MUST be rejected.
CLIENT_DELETE_PROHIBITED = 'clientDeleteProhibited'
SERVER_DELETE_PROHIBITED = 'serverDeleteProhibited'
# Requests to transfer the object MUST be rejected.
CLIENT_TRANSFER_PROHIBITED = 'clientTransferProhibited'
SERVER_TRANSFER_PROHIBITED = 'serverTransferProhibited'
# The contact object has at least one active association with
# another object, such as a domain object. Servers SHOULD provide
# services to determine existing object associations.
# "linked" status MAY be combined with any status.
LINKED = 'linked'
# This is the normal status value for an object that has no pending
# operations or prohibitions. This value is set and removed by the
# server as other status values are added or removed.
# "ok" status MAY only be combined with "linked" status.
OK = 'ok'
# Requests to update the object (other than to remove this status) MUST be rejected.
CLIENT_UPDATE_PROHIBITED = 'clientUpdateProhibited'
SERVER_UPDATE_PROHIBITED = 'serverUpdateProhibited'
# A transform command has been processed for the object, but the
# action has not been completed by the server. Server operators can
# delay action completion for a variety of reasons, such as to allow
# for human review or third-party action. A transform command that
# is processed, but whose requested action is pending, is noted with
# response code 1001.
# When the requested action has been completed, the pendingCreate,
# pendingDelete, pendingTransfer, or pendingUpdate status value MUST be
# removed. All clients involved in the transaction MUST be notified
# using a service message that the action has been completed and that
# the status of the object has changed.
# The pendingCreate, pendingDelete, pendingTransfer, and pendingUpdate
# status values MUST NOT be combined with each other.
PENDING_CREATE = 'pendingCreate'
# "pendingTransfer" status MUST NOT be combined with either
# "clientTransferProhibited" or "serverTransferProhibited" status.
PENDING_TRANSFER = 'pendingTransfer'
# "pendingUpdate" status MUST NOT be combined with either
# "clientUpdateProhibited" or "serverUpdateProhibited" status.
PENDING_UPDATE = 'pendingUpdate'
# "pendingDelete" MUST NOT be combined with either
# "clientDeleteProhibited" or "serverDeleteProhibited" status.
PENDING_DELETE = 'pendingDelete'
STATUSES = [
CLIENT_DELETE_PROHIBITED, SERVER_DELETE_PROHIBITED,
CLIENT_TRANSFER_PROHIBITED,
SERVER_TRANSFER_PROHIBITED, CLIENT_UPDATE_PROHIBITED, SERVER_UPDATE_PROHIBITED,
OK, PENDING_CREATE, PENDING_DELETE, PENDING_TRANSFER,
PENDING_UPDATE, LINKED
]
CLIENT_STATUSES = [
CLIENT_DELETE_PROHIBITED, CLIENT_TRANSFER_PROHIBITED,
CLIENT_UPDATE_PROHIBITED
]
SERVER_STATUSES = [
SERVER_UPDATE_PROHIBITED,
SERVER_DELETE_PROHIBITED,
SERVER_TRANSFER_PROHIBITED
]
#
# END OF STATUSES
#
class << self class << self
def search_by_query(query) def search_by_query(query)
res = search(code_cont: query).result res = search(code_cont: query).result
@ -83,6 +164,20 @@ class Contact < ActiveRecord::Base
def privs def privs
where("ident_type = '#{PRIV}'") where("ident_type = '#{PRIV}'")
end end
def admin_statuses
[
SERVER_UPDATE_PROHIBITED,
SERVER_DELETE_PROHIBITED
]
end
def admin_statuses_map
[
['UpdateProhibited', SERVER_UPDATE_PROHIBITED],
['DeleteProhibited', SERVER_DELETE_PROHIBITED]
]
end
end end
def roid def roid
@ -104,6 +199,12 @@ class Contact < ActiveRecord::Base
end end
end end
def uniq_statuses?
return true unless statuses.detect { |s| statuses.count(s) > 1 }
errors.add(:statuses, :not_uniq)
false
end
def bic? def bic?
ident_type == BIC ident_type == BIC
end end
@ -206,4 +307,78 @@ class Contact < ActiveRecord::Base
@desc @desc
end end
def status_notes_array=(notes)
self.status_notes = {}
notes ||= []
statuses.each_with_index do |status,i|
self.status_notes[status] = notes[i]
end
end
private
def manage_linked
if domains.present?
statuses << LINKED if statuses.detect { |s| s == LINKED }.blank?
else
statuses.delete_if { |s| s == LINKED }
end
end
# rubocop:disable Metrics/CyclomaticComplexity
def manage_ok
return unset_ok unless valid?
case statuses.size
when 0
set_ok
when 1
set_ok if statuses == [LINKED]
when 2
return if statuses.sort == [LINKED, OK]
unset_ok
else
unset_ok
end
end
# rubocop:enable Metrics/CyclomaticComplexity
def unset_ok
statuses.delete_if { |s| s == OK }
end
def set_ok
statuses << OK if statuses.detect { |s| s == OK }.blank?
end
def linked?
statuses.include?(LINKED)
end
def update_prohibited?
(statuses & [
CLIENT_UPDATE_PROHIBITED,
SERVER_UPDATE_PROHIBITED,
CLIENT_TRANSFER_PROHIBITED,
SERVER_TRANSFER_PROHIBITED,
PENDING_CREATE,
PENDING_TRANSFER,
PENDING_UPDATE,
PENDING_DELETE
]).present?
end
def delete_prohibited?
(statuses & [
CLIENT_DELETE_PROHIBITED,
SERVER_DELETE_PROHIBITED,
CLIENT_TRANSFER_PROHIBITED,
SERVER_TRANSFER_PROHIBITED,
PENDING_CREATE,
PENDING_TRANSFER,
PENDING_UPDATE,
PENDING_DELETE
]).present?
end
end end

View file

@ -1,124 +0,0 @@
class ContactStatus < ActiveRecord::Base
include Versions # version/contact_status_version.rb
include EppErrors
belongs_to :contact
# Requests to delete the object MUST be rejected.
CLIENT_DELETE_PROHIBITED = 'clientDeleteProhibited'
SERVER_DELETE_PROHIBITED = 'serverDeleteProhibited'
# Requests to transfer the object MUST be rejected.
CLIENT_TRANSFER_PROHIBITED = 'clientTransferProhibited'
SERVER_TRANSFER_PROHIBITED = 'serverTransferProhibited'
# The contact object has at least one active association with
# another object, such as a domain object. Servers SHOULD provide
# services to determine existing object associations.
# "linked" status MAY be combined with any status.
LINKED = 'linked'
# This is the normal status value for an object that has no pending
# operations or prohibitions. This value is set and removed by the
# server as other status values are added or removed.
# "ok" status MAY only be combined with "linked" status.
OK = 'ok'
# Requests to update the object (other than to remove this status) MUST be rejected.
CLIENT_UPDATE_PROHIBITED = 'clientUpdateProhibited'
SERVER_UPDATE_PROHIBITED = 'serverUpdateProhibited'
# A transform command has been processed for the object, but the
# action has not been completed by the server. Server operators can
# delay action completion for a variety of reasons, such as to allow
# for human review or third-party action. A transform command that
# is processed, but whose requested action is pending, is noted with
# response code 1001.
# When the requested action has been completed, the pendingCreate,
# pendingDelete, pendingTransfer, or pendingUpdate status value MUST be
# removed. All clients involved in the transaction MUST be notified
# using a service message that the action has been completed and that
# the status of the object has changed.
# The pendingCreate, pendingDelete, pendingTransfer, and pendingUpdate
# status values MUST NOT be combined with each other.
PENDING_CREATE = 'pendingCreate'
# "pendingTransfer" status MUST NOT be combined with either
# "clientTransferProhibited" or "serverTransferProhibited" status.
PENDING_TRANSFER = 'pendingTransfer'
# "pendingUpdate" status MUST NOT be combined with either
# "clientUpdateProhibited" or "serverUpdateProhibited" status.
PENDING_UPDATE = 'pendingUpdate'
# "pendingDelete" MUST NOT be combined with either
# "clientDeleteProhibited" or "serverDeleteProhibited" status.
PENDING_DELETE = 'pendingDelete'
STATUSES = [
CLIENT_DELETE_PROHIBITED, SERVER_DELETE_PROHIBITED,
CLIENT_TRANSFER_PROHIBITED,
SERVER_TRANSFER_PROHIBITED, CLIENT_UPDATE_PROHIBITED, SERVER_UPDATE_PROHIBITED,
OK, PENDING_CREATE, PENDING_DELETE, PENDING_TRANSFER,
PENDING_UPDATE, LINKED
]
CLIENT_STATUSES = [
CLIENT_DELETE_PROHIBITED, CLIENT_TRANSFER_PROHIBITED,
CLIENT_UPDATE_PROHIBITED
]
SERVER_STATUSES = [
SERVER_DELETE_PROHIBITED, SERVER_TRANSFER_PROHIBITED,
SERVER_UPDATE_PROHIBITED
]
class << self
def manage(statuses, contact)
manage_linked(statuses, contact)
manage_ok(statuses, contact)
end
def manage_linked(statuses, contact)
if contact.domains.present?
create(value: LINKED, contact_id: contact.id) if statuses.select { |s| s.value == LINKED }.blank?
else
statuses.select { |s| s.value == LINKED }.each(&:destroy)
end
end
def manage_ok(statuses, contact)
if statuses.present?
if contact.valid?
else
statuses.select { |s| s.value == OK }.each(&:destroy)
end
else
create(value: OK, contact_id: contact.id)
end
end
end
def epp_code_map
{
'2302' => [ # Object exists
[:value, :taken, { value: { obj: 'status', val: value } }]
]
}
end
def server_status?
SERVER_STATUSES.include?(value)
end
def client_status?
CLIENT_STATUSES.include?(value)
end
class << self
def statuses_for_client
CLIENT_STATUSES.map { |x| x.sub('client', '') }
end
def statuses_for_admin
SERVER_STATUSES.map { |x| x.sub('server', '') }
end
end
end

View file

@ -136,13 +136,12 @@ module Depp
end end
hash hash
end end
end
def initialize(attributes = {}) def type_string(type_code)
super return '' if type_code.blank?
self.country_code = 'EE' if country_code.blank? t = SELECTION_TYPES.select { |tp| tp.second == type_code }
self.ident_type = 'bic' if ident_type.blank? t.try(:first).try(:first)
self.ident_country_code = 'EE' if ident_country_code.blank? end
end end
def save def save

View file

@ -0,0 +1,5 @@
class DepricatedContactStatus < ActiveRecord::Base
self.table_name = :contact_statuses
self.sequence_name = :contact_statuses_id_seq
belongs_to :contact
end

View file

@ -54,9 +54,10 @@ class Domain < ActiveRecord::Base
delegate :name, to: :registrar, prefix: true delegate :name, to: :registrar, prefix: true
delegate :street, to: :registrar, prefix: true delegate :street, to: :registrar, prefix: true
after_initialize :init_default_values after_initialize do
def init_default_values
self.pending_json = {} if pending_json.blank? self.pending_json = {} if pending_json.blank?
self.statuses = [] if statuses.nil?
self.status_notes = {} if status_notes.nil?
end end
before_create :generate_auth_info before_create :generate_auth_info
@ -77,7 +78,6 @@ class Domain < ActiveRecord::Base
end end
after_save :update_whois_record after_save :update_whois_record
after_initialize -> { self.statuses = [] if statuses.nil? }
after_create :update_reserved_domains after_create :update_reserved_domains
def update_reserved_domains def update_reserved_domains

View file

@ -4,6 +4,13 @@ class Epp::Contact < Contact
# disable STI, there is type column present # disable STI, there is type column present
self.inheritance_column = :sti_disabled self.inheritance_column = :sti_disabled
before_validation :manage_permissions
def manage_permissions
return unless update_prohibited? || delete_prohibited?
add_epp_error('2304', nil, nil, I18n.t(:object_status_prohibits_operation))
false
end
class << self class << self
# support legacy search # support legacy search
def find_by_epp_code(code) def find_by_epp_code(code)
@ -125,7 +132,9 @@ class Epp::Contact < Contact
[:ident, :invalid], [:ident, :invalid],
[:ident, :invalid_EE_identity_format], [:ident, :invalid_EE_identity_format],
[:ident, :invalid_birthday_format], [:ident, :invalid_birthday_format],
[:ident, :invalid_country_code] [:ident, :invalid_country_code],
[:code, :invalid],
[:code, :too_long_contact_code]
], ],
'2302' => [ # Object exists '2302' => [ # Object exists
[:code, :epp_id_taken] [:code, :epp_id_taken]

View file

@ -9,6 +9,21 @@ class Epp::Domain < Domain
false false
end end
before_validation :validate_contacts
def validate_contacts
return if contacts.map {|c| c.valid? }.all?
add_epp_error('2304', nil, nil, I18n.t(:object_status_prohibits_operation))
false
end
before_save :update_contact_status
def update_contact_status
contacts.each do |c|
next if c.linked?
c.save(validate: false)
end
end
class << self class << self
def new_from_epp(frame, current_user) def new_from_epp(frame, current_user)
domain = Epp::Domain.new domain = Epp::Domain.new
@ -399,7 +414,7 @@ class Epp::Domain < Domain
statuses.delete(DomainStatus::PENDING_UPDATE) statuses.delete(DomainStatus::PENDING_UPDATE)
return unless update(frame, user, false) return unless update(frame, user, false)
clean_pendings! clean_pendings!
self.deliver_emails = true # turn on email delivery for epp self.deliver_emails = true # turn on email delivery for epp
DomainMailer.registrant_updated(self).deliver_now DomainMailer.registrant_updated(self).deliver_now
end end
@ -446,8 +461,8 @@ class Epp::Domain < Domain
p = self.class.convert_period_to_time(period, unit) p = self.class.convert_period_to_time(period, unit)
self.valid_to = valid_to + p self.valid_to = valid_to + p
self.outzone_at = outzone_at + p self.outzone_at = valid_to + Setting.expire_warning_period.days
self.delete_at = delete_at + p self.delete_at = outzone_at + Setting.redemption_grace_period.days
self.period = period self.period = period
self.period_unit = unit self.period_unit = unit
@ -473,7 +488,6 @@ class Epp::Domain < Domain
when 'reject' when 'reject'
return reject_transfer(frame, current_user) if pending_transfer return reject_transfer(frame, current_user) if pending_transfer
end end
add_epp_error('2303', nil, nil, I18n.t('no_transfers_found'))
end end
# TODO: Eager load problems here. Investigate how it's possible not to query contact again # TODO: Eager load problems here. Investigate how it's possible not to query contact again
@ -485,7 +499,7 @@ class Epp::Domain < Domain
def copy_and_transfer_contact(contact_id, registrar_id) def copy_and_transfer_contact(contact_id, registrar_id)
c = Contact.find(contact_id) # n+1 workaround c = Contact.find(contact_id) # n+1 workaround
oc = c.deep_clone include: [:statuses] oc = c.deep_clone
oc.code = nil oc.code = nil
oc.registrar_id = registrar_id oc.registrar_id = registrar_id
oc.prefix_code oc.prefix_code
@ -536,50 +550,48 @@ class Epp::Domain < Domain
end end
end end
end end
# rubocop: enable Metrics/PerceivedComplexity # rubocop: enable Metrics/PerceivedComplexity
# rubocop: enable Metrics/CyclomaticComplexity # rubocop: enable Metrics/CyclomaticComplexity
# rubocop: disable Metrics/MethodLength # rubocop: disable Metrics/MethodLength
# rubocop: disable Metrics/AbcSize # rubocop: disable Metrics/AbcSize
def query_transfer(frame, current_user) def query_transfer(frame, current_user)
return false unless can_be_transferred_to?(current_user.registrar) unless can_be_transferred_to?(current_user.registrar)
throw :epp_error, {
code: '2002',
msg: I18n.t(:domain_already_belongs_to_the_querying_registrar)
}
end
old_contact_codes = contacts.pluck(:code).sort.uniq old_contact_codes = contacts.pluck(:code).sort.uniq
old_registrant_code = registrant.code old_registrant_code = registrant.code
transaction do transaction do
begin dt = domain_transfers.create!(
dt = domain_transfers.create!( transfer_requested_at: Time.zone.now,
transfer_requested_at: Time.zone.now, transfer_to: current_user.registrar,
transfer_to: current_user.registrar, transfer_from: registrar
transfer_from: registrar )
if dt.pending?
registrar.messages.create!(
body: I18n.t('transfer_requested'),
attached_obj_id: dt.id,
attached_obj_type: dt.class.to_s
) )
if dt.pending?
registrar.messages.create!(
body: I18n.t('transfer_requested'),
attached_obj_id: dt.id,
attached_obj_type: dt.class.to_s
)
end
if dt.approved?
transfer_contacts(current_user.registrar_id)
dt.notify_losing_registrar(old_contact_codes, old_registrant_code)
generate_auth_info
self.registrar = current_user.registrar
end
attach_legal_document(self.class.parse_legal_document_from_frame(frame))
save!(validate: false)
return dt
rescue => e
add_epp_error('2306', nil, nil, I18n.t('action_failed_due_to_server_error'))
logger.error('DOMAIN TRANSFER FAILED')
logger.error(e)
raise ActiveRecord::Rollback
end end
if dt.approved?
transfer_contacts(current_user.registrar_id)
dt.notify_losing_registrar(old_contact_codes, old_registrant_code)
generate_auth_info
self.registrar = current_user.registrar
end
attach_legal_document(self.class.parse_legal_document_from_frame(frame))
save!(validate: false)
return dt
end end
end end
# rubocop: enable Metrics/AbcSize # rubocop: enable Metrics/AbcSize
@ -588,27 +600,24 @@ class Epp::Domain < Domain
def approve_transfer(frame, current_user) def approve_transfer(frame, current_user)
pt = pending_transfer pt = pending_transfer
if current_user.registrar != pt.transfer_from if current_user.registrar != pt.transfer_from
add_epp_error('2304', nil, nil, I18n.t('transfer_can_be_approved_only_by_current_registrar')) throw :epp_error, {
return false msg: I18n.t('transfer_can_be_approved_only_by_current_registrar'),
code: '2304'
}
end end
transaction do transaction do
begin pt.update!(
pt.update!( status: DomainTransfer::CLIENT_APPROVED,
status: DomainTransfer::CLIENT_APPROVED, transferred_at: Time.zone.now
transferred_at: Time.zone.now )
)
transfer_contacts(pt.transfer_to_id) transfer_contacts(pt.transfer_to_id)
generate_auth_info generate_auth_info
self.registrar = pt.transfer_to self.registrar = pt.transfer_to
attach_legal_document(self.class.parse_legal_document_from_frame(frame)) attach_legal_document(self.class.parse_legal_document_from_frame(frame))
save!(validate: false) save!(validate: false)
rescue => _e
add_epp_error('2306', nil, nil, I18n.t('action_failed_due_to_server_error'))
raise ActiveRecord::Rollback
end
end end
pt pt
@ -617,22 +626,19 @@ class Epp::Domain < Domain
def reject_transfer(frame, current_user) def reject_transfer(frame, current_user)
pt = pending_transfer pt = pending_transfer
if current_user.registrar != pt.transfer_from if current_user.registrar != pt.transfer_from
add_epp_error('2304', nil, nil, I18n.t('transfer_can_be_rejected_only_by_current_registrar')) throw :epp_error, {
return false msg: I18n.t('transfer_can_be_rejected_only_by_current_registrar'),
code: '2304'
}
end end
transaction do transaction do
begin pt.update!(
pt.update!( status: DomainTransfer::CLIENT_REJECTED
status: DomainTransfer::CLIENT_REJECTED )
)
attach_legal_document(self.class.parse_legal_document_from_frame(frame)) attach_legal_document(self.class.parse_legal_document_from_frame(frame))
save!(validate: false) save!(validate: false)
rescue => _e
add_epp_error('2306', nil, nil, I18n.t('action_failed_due_to_server_error'))
raise ActiveRecord::Rollback
end
end end
pt pt
@ -709,11 +715,7 @@ class Epp::Domain < Domain
end end
def can_be_transferred_to?(new_registrar) def can_be_transferred_to?(new_registrar)
if new_registrar == registrar new_registrar != registrar
errors.add(:base, :domain_already_belongs_to_the_querying_registrar)
return false
end
true
end end
## SHARED ## SHARED

View file

@ -13,6 +13,35 @@
= f.label :iban = f.label :iban
.col-md-8 .col-md-8
= f.text_field(:iban, class: 'form-control') = f.text_field(:iban, class: 'form-control')
- if @invoice
%hr
%h4= t('bank_transaction')
%hr
= f.fields_for :bank_transactions, [@bank_transaction] do |x|
.row
.col-md-8
.form-group
= x.label :description, class: 'col-md-4 control-label required'
.col-md-8
= x.text_field(:description, class: 'form-control', required: true)
.form-group
= x.label :sum, class: 'col-md-4 control-label required'
.col-md-8
= x.text_field(:sum, class: 'form-control', required: true)
.form-group
= x.label :currency, class: 'col-md-4 control-label required'
.col-md-8
= x.text_field(:currency, class: 'form-control', required: true, readonly: true)
.form-group
= x.label :reference_no, class: 'col-md-4 control-label required'
.col-md-8
= x.text_field(:reference_no, class: 'form-control', required: true)
.form-group
= x.label :paid_at, class: 'col-md-4 control-label required'
.col-md-8
= x.text_field(:paid_at, class: 'form-control datepicker', required: true)
%hr %hr
.row .row
.col-md-8.text-right .col-md-8.text-right

View file

@ -1,5 +1,6 @@
- content_for :actions do - content_for :actions do
= link_to(t(:back), admin_bank_statement_path(@bank_statement), class: 'btn btn-default') - if @bank_statement.persisted?
= link_to(t(:back), admin_bank_statement_path(@bank_statement), class: 'btn btn-default')
= render 'shared/title', name: t(:create_bank_transaction) = render 'shared/title', name: t(:create_bank_transaction)

View file

@ -0,0 +1,11 @@
= form_for([:admin, contact], html: { class: 'form-horizontal' }) do |f|
.errors
= render 'shared/errors', object: contact
.row
.col-md-8
.tab-content{style:'margin-top: 20px;'}
#general-tab.tab-pane.active
= render 'admin/contacts/form_partials/statuses', f: f
.row
.col-md-8.text-right
= button_tag(t(:save), class: 'btn btn-primary')

View file

@ -0,0 +1,6 @@
- content_for :actions do
= link_to(t(:add_new_status), '#', class: 'btn btn-primary js-add-contact-status')
= link_to(t(:back_to_contact), [:admin, @contact], class: 'btn btn-default')
= render 'shared/title', name: "#{t(:edit)}: #{@contact.name}"
= render 'form', contact: @contact

View file

@ -0,0 +1,41 @@
#js-contact-statuses
- f.object.statuses.each do |s|
- disabled = !Contact.admin_statuses.include?(s)
- disabled_style = disabled ? 'display: none' : ''
- delete_style = [Contact::OK, Contact::LINKED].include?(s) ? 'display: none' : ''
.panel.panel-default
.panel-heading.clearfix
.pull-left= t(:status)
.pull-right
= link_to(t(:delete), '#', class: 'btn btn-danger btn-xs js-destroy-status', style: delete_style)
.panel-body
.form-group
= f.label 'status', class: 'col-md-2 control-label'
.col-md-10
.js-select{style: disabled_style}
= select_tag 'contact[statuses][]',
options_for_select(Contact::admin_statuses_map, s),
include_blank: true, class: "form-control"
- if disabled
.disabled-value.js-disabled-value
= s
= hidden_field_tag 'contact[statuses][]', s, readonly: true
.form-group
= label_tag t(:notes), nil, class: 'col-md-2 control-label'
.col-md-10
- value = f.object.new_record? ? '' : f.object.status_notes[s]
= text_field_tag 'contact[status_notes_array][]', value, class: 'form-control'
:coffee
$("#js-contact-statuses").nestedAttributes
bindAddTo: $(".js-add-contact-status")
afterAdd: (el) ->
if el.find('.js-disabled-value')
el.find('.js-disabled-value').remove()
el.find('.js-select').show()
el.find('.js-destroy-status').show()
$(document).on 'click', '.js-destroy-status', (e) ->
e.preventDefault()
$(this).parents('.panel').remove()

View file

@ -12,7 +12,6 @@
%br %br
%dt= t(:ident) %dt= t(:ident)
%dd= ident_for(@contact) %dd= ident_for(@contact)

View file

@ -7,12 +7,12 @@
%thead %thead
%tr %tr
%th{class: 'col-xs-6'}= t(:status) %th{class: 'col-xs-6'}= t(:status)
%th{class: 'col-xs-6'}= t(:description) %th{class: 'col-xs-6'}= t(:notes)
%tbody %tbody
- contact.statuses.each do |s| - contact.statuses.each do |status|
%tr %tr
%td= s.value %td= status
%td= s.description %td= contact.status_notes[status]
- if contact.errors.messages[:statuses] - if contact.errors.messages[:statuses]
%tfoot %tfoot

View file

@ -1,3 +1,5 @@
- content_for :actions do
= link_to(t(:edit_statuses), edit_admin_contact_path(@contact), class: 'btn btn-primary')
= render 'shared/title', name: @contact.name = render 'shared/title', name: @contact.name
.row .row

View file

@ -1,125 +1,126 @@
- children = HashWithIndifferentAccess.new(version.children) - if version.present? && domain.present?
- nameservers = children[:nameservers] || [] - children = HashWithIndifferentAccess.new(version.children)
- tech_contacts = children[:tech_contacts] || [] - nameservers = children[:nameservers] || []
- admin_contacts = children[:admin_contacts] || [] - tech_contacts = children[:tech_contacts] || []
- registrant = children[:registrant] || [] - admin_contacts = children[:admin_contacts] || []
- registrant = children[:registrant] || []
%td %td
%p.nowrap %p.nowrap
= l(domain.updated_at, format: :short) = l(domain.updated_at, format: :short)
= version.event = version.event
%p.text-right %p.text-right
= version.terminator = version.terminator
%td %td
%p
= "#{domain.period}#{domain.period_unit}"
= "#{l(domain.valid_from, format: :date)} - #{l(domain.valid_to, format: :date)}"
%p
= domain.status
%td
- registrant.each do |oc|
%p %p
= oc[:name] = "#{domain.period}#{domain.period_unit}"
= oc[:phone] = "#{l(domain.valid_from, format: :date)} - #{l(domain.valid_to, format: :date)}"
= oc[:email]
%p %p
= oc[:code] = domain.status
%td %td
- admin_contacts.each do |ac| - registrant.each do |oc|
%p
= oc[:name]
= oc[:phone]
= oc[:email]
%p
= oc[:code]
%td
- admin_contacts.each do |ac|
%p
= ac[:name]
= ac[:phone]
= ac[:email]
%p
= ac[:code]
%td
- tech_contacts.each do |tc|
%p
= tc[:name]
= tc[:phone]
= tc[:email]
%p
= tc[:code]
%td
- nameservers.each do |ns|
%p
= ns[:hostname]
%br
= ns[:ipv4]
= ns[:ipv6]
%td
%p %p
= ac[:name] = domain.registrar.name
= ac[:phone]
= ac[:email]
%p
= ac[:code]
%td -# %td
- tech_contacts.each do |tc| -# = version.children.inspect
%p
= tc[:name]
= tc[:phone]
= tc[:email]
%p
= tc[:code]
%td -# %td{ class: changes.include?(:domain) ? 'edit-highlight' : 'no-highlight' }
- nameservers.each do |ns| -# - if children[:domain]
%p
= ns[:hostname]
%br
= ns[:ipv4]
= ns[:ipv6]
%td
%p
= domain.registrar.name
-# %td
-# = version.children.inspect
-# %td{ class: changes.include?(:domain) ? 'edit-highlight' : 'no-highlight' }
-# - if children[:domain]
-# %p{:style => "font-size:x-small;"}
-# = children[:domain][:period]
-# = children[:domain][:period_unit] if children[:domain][:period]
-# - if children[:domain][:valid_to] && children[:domain][:valid_from]
-# = ","
-# = l(children[:domain][:valid_from], format: :date) + '-' + l(children[:domain][:valid_to], format: :date)
-# - if children[:domain].try(:[], :registrar_id)
-# = ","
-# = Registrar.find(children[:domain][:registrar_id]).try(:name)
-# - if children[:domain][:status]
-# = ',' + children[:domain][:status]
-# %td{ class: changes.include?(:registrant) ? 'edit-highlight' : 'no-highlight' }
-# - if children[:registrant]
-# %p{:style => "font-size:x-small;"}
-# = children[:registrant][:name]
-# = ","
-# = children[:registrant][:phone]
-# = ","
-# = children[:registrant][:email]
-# = ","
-# = children[:registrant][:code]
-# %td{ class: changes.include?(:admin_contacts) ? 'edit-highlight' : 'no-highlight' }
-# - if children[:admin_contacts]
-# - children[:admin_contacts].each do |ac|
-# %p{:style => "font-size:x-small;"} -# %p{:style => "font-size:x-small;"}
-# = ac[:name] -# = children[:domain][:period]
-# = "," -# = children[:domain][:period_unit] if children[:domain][:period]
-# = ac[:phone] -# - if children[:domain][:valid_to] && children[:domain][:valid_from]
-# = "," -# = ","
-# = ac[:email] -# = l(children[:domain][:valid_from], format: :date) + '-' + l(children[:domain][:valid_to], format: :date)
-# = "," -# - if children[:domain].try(:[], :registrar_id)
-# = ac[:code] -# = ","
-# = Registrar.find(children[:domain][:registrar_id]).try(:name)
-# - if children[:domain][:status]
-# = ',' + children[:domain][:status]
-# %td{ class: changes.include?(:tech_contacts) ? 'edit-highlight' : 'no-highlight' }
-# - if children[:tech_contacts] -# %td{ class: changes.include?(:registrant) ? 'edit-highlight' : 'no-highlight' }
-# - children[:tech_contacts].each do |tc| -# - if children[:registrant]
-# %p{:style => "font-size:x-small;"} -# %p{:style => "font-size:x-small;"}
-# = tc[:name] -# = children[:registrant][:name]
-# = "," -# = ","
-# = tc[:phone] -# = children[:registrant][:phone]
-# = "," -# = ","
-# = tc[:email] -# = children[:registrant][:email]
-# = "," -# = ","
-# = tc[:code] -# = children[:registrant][:code]
-# %td{ class: changes.include?(:nameservers) ? 'edit-highlight' : 'no-highlight' } -# %td{ class: changes.include?(:admin_contacts) ? 'edit-highlight' : 'no-highlight' }
-# - if children[:nameservers] -# - if children[:admin_contacts]
-# - children[:nameservers].each do |ns| -# - children[:admin_contacts].each do |ac|
-# %p{:style => "font-size:x-small;"} -# %p{:style => "font-size:x-small;"}
-# = ns[:hostname] -# = ac[:name]
-# = "," -# = ","
-# = ns[:ipv4] || ns[:ipv6] -# = ac[:phone]
-# = ","
-# = ac[:email]
-# = ","
-# = ac[:code]
-# %td -# %td{ class: changes.include?(:tech_contacts) ? 'edit-highlight' : 'no-highlight' }
-# %p{ :style => 'font-size:x-small;' } -# - if children[:tech_contacts]
-# = l(version.created_at, format: :short) -# - children[:tech_contacts].each do |tc|
-# = whodunnit_with_protocol(version.whodunnit) -# %p{:style => "font-size:x-small;"}
-# = version.event -# = tc[:name]
-# = ","
-# = tc[:phone]
-# = ","
-# = tc[:email]
-# = ","
-# = tc[:code]
-# %td{ class: changes.include?(:nameservers) ? 'edit-highlight' : 'no-highlight' }
-# - if children[:nameservers]
-# - children[:nameservers].each do |ns|
-# %p{:style => "font-size:x-small;"}
-# = ns[:hostname]
-# = ","
-# = ns[:ipv4] || ns[:ipv6]
-# %td
-# %p{ :style => 'font-size:x-small;' }
-# = l(version.created_at, format: :short)
-# = whodunnit_with_protocol(version.whodunnit)
-# = version.event

View file

@ -10,7 +10,3 @@
.row .row
.col-md-8.text-right .col-md-8.text-right
= button_tag(t(:save), class: 'btn btn-primary') = button_tag(t(:save), class: 'btn btn-primary')
:coffee
$ ->
$("#tabs a:first").tab "show"

View file

@ -1,9 +1,11 @@
.row .row
.col-sm-6 .col-sm-4
%h1.text-center-xs %h1.text-center-xs
= @invoice = @invoice
.col-sm-6 .col-sm-8
%h1.text-right.text-center-xs %h1.text-right.text-center-xs
- unless @invoice.binded?
= link_to(t(:payment_received), new_admin_bank_statement_path(invoice_id: @invoice.id), class: 'btn btn-default')
= link_to(t(:download), admin_invoice_download_pdf_path(@invoice), class: 'btn btn-default') = 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') = link_to(t(:forward), admin_invoice_forward_path(@invoice), class: 'btn btn-default')
- if !@invoice.cancelled? && !@invoice.binded? - if !@invoice.cancelled? && !@invoice.binded?

View file

@ -71,6 +71,7 @@
= render 'setting_row', var: :registry_vat_no = render 'setting_row', var: :registry_vat_no
= render 'setting_row', var: :registry_vat_prc = render 'setting_row', var: :registry_vat_prc
= render 'setting_row', var: :registry_bank = render 'setting_row', var: :registry_bank
= render 'setting_row', var: :registry_bank_code
= render 'setting_row', var: :registry_iban = render 'setting_row', var: :registry_iban
= render 'setting_row', var: :registry_swift = render 'setting_row', var: :registry_swift

View file

@ -10,7 +10,7 @@ xml.epp_head do
xml.tag!('contact:roid', @contact.roid) xml.tag!('contact:roid', @contact.roid)
@contact.statuses.each do |status| @contact.statuses.each do |status|
xml.tag!('contact:status', s: status.value) xml.tag!('contact:status', s: status)
end end
xml.tag!('contact:postalInfo', type: 'int') do xml.tag!('contact:postalInfo', type: 'int') do

View file

@ -30,5 +30,7 @@
.col-md-3.control-label .col-md-3.control-label
= f.label :country_code, t(:country) + '*' = f.label :country_code, t(:country) + '*'
.col-md-7 .col-md-7
= f.select :country_code, - country_selected = f.object.persisted? ? f.object.country_code : 'EE'
SortedCountry.all_options(f.object.country_code) = f.select(:country_code, SortedCountry.all_options(country_selected),
{ include_blank: true }, required: true)

View file

@ -6,24 +6,41 @@
.col-md-3.control-label .col-md-3.control-label
= f.label :ident_country_code, t(:country) + '*' = f.label :ident_country_code, t(:country) + '*'
.col-md-7 .col-md-7
= f.select(:ident_country_code, SortedCountry.all_options(f.object.ident_country_code), {}, - if @contact.persisted? && f.object.ident_country_code.present?
class: 'js-ident-country-code', required: true, disabled: @contact.persisted?) .disabled-value
= Country.new(f.object.ident_country_code).try(:to_s)
= " [#{f.object.ident_country_code}]"
- else
- country_selected = @contact.persisted? ? '' : 'EE'
= f.select(:ident_country_code, SortedCountry.all_options(country_selected), {},
class: 'js-ident-country-code', required: true)
.form-group .form-group
.col-md-3.control-label .col-md-3.control-label
= f.label :ident_type, t(:type) + '*' = f.label :ident_type, t(:type) + '*'
.col-md-7 .col-md-7
= f.select(:ident_type, Depp::Contact::SELECTION_TYPES, { selected: f.object.ident_type }, - if @contact.persisted? && f.object.ident_type.present?
class: 'js-ident-type', required: true, disabled: @contact.persisted?) .disabled-value
= Depp::Contact.type_string(f.object.ident_type)
= " [#{f.object.ident_type}]"
- else
- type_selected = @contact.persisted? ? '' : 'bic'
= f.select(:ident_type, Depp::Contact::SELECTION_TYPES,
{ selected: type_selected },
class: 'js-ident-type', required: true)
.form-group .form-group
.col-md-3.control-label .col-md-3.control-label
= f.label :ident, t(:ident) + '*' = f.label :ident, t(:ident) + '*'
.col-md-7 .col-md-7
= f.text_field :ident, class: 'form-control', required: true, disabled: @contact.persisted? - if f.object.ident.present?
- tip_visibility = f.object.ident_type == 'birthday' ? '' : 'display: none' .disabled-value
.js-ident-tip{ style: tip_visibility } = f.object.ident
= t(:birthday_format) - else
= f.text_field :ident, class: 'form-control', required: true, disabled: @contact.persisted?
- tip_visibility = f.object.ident_type == 'birthday' ? '' : 'display: none'
.js-ident-tip{ style: tip_visibility }
= t(:birthday_format)
.panel.panel-default .panel.panel-default
.panel-heading.clearfix .panel-heading.clearfix

View file

@ -2,5 +2,5 @@
- object.errors.each do |attr, err| - object.errors.each do |attr, err|
- next if attr.match(/\./) - next if attr.match(/\./)
- next if attr == :epp_errors - next if attr == :epp_errors
= err = "#{attr.to_s.humanize} #{err}"
%br %br

View file

@ -4,7 +4,7 @@ app_name: '.EE Registry'
zonefile_export_dir: 'export/zonefiles' zonefile_export_dir: 'export/zonefiles'
bank_statement_import_dir: 'import/bank_statements' bank_statement_import_dir: 'import/bank_statements'
legal_documents_dir: 'import/legal_documents' legal_documents_dir: 'import/legal_documents'
time_zone: 'Tallinn' # more zones by rake time:zones:all time_zone: 'Tallinn' # more zones by rake time:zones:all
# New Relic app name, keep only current mode, remove other names. # New Relic app name, keep only current mode, remove other names.
# Example: 'Admin, EPP, REPP' will have name 'Admin, EPP, REPP - production' at New Relic. # Example: 'Admin, EPP, REPP' will have name 'Admin, EPP, REPP - production' at New Relic.
@ -25,12 +25,16 @@ ca_key_path: '/home/registry/registry/shared/ca/private/ca.key.pem'
ca_key_password: 'your-root-key-password' ca_key_password: 'your-root-key-password'
# EPP server configuration # EPP server configuration
webclient_ip: '127.0.0.1' webclient_ips: '127.0.0.1,0.0.0.0' #ips, separated with commas
webclient_cert_common_name: 'webclient' webclient_cert_common_name: 'webclient'
# Contact epp will not accept org value by default # Contact epp will not accept org value by default
# and returns 2306 "Parameter value policy error" # and returns 2306 "Parameter value policy error"
contact_org_enabled: 'false' contact_org_enabled: 'false'
# Overwrite rack default trusted proxies list in order to
# enable test external interfaces EPP/REPP from webserver network
# eis_trusted_proxies: '1.1.1.1,2.2.2.2' #ips, separated with commas
# Enable iptables counter updater # Enable iptables counter updater
# iptables_counter_enabled: 'true' # iptables_counter_enabled: 'true'
@ -72,7 +76,7 @@ sk_digi_doc_service_name: 'EIS test'
# Autotest config overwrites # Autotest config overwrites
test: test:
webclient_ip: '127.0.0.1' # it should match to localhost ip address webclient_ips: '127.0.0.1' # it should match to localhost ip address
crl_dir: '/var/lib/jenkins/workspace/registry/ca/crl' crl_dir: '/var/lib/jenkins/workspace/registry/ca/crl'
crl_path: '/var/lib/jenkins/workspace/registry/ca/crl/crl.pem' crl_path: '/var/lib/jenkins/workspace/registry/ca/crl/crl.pem'
ca_cert_path: '/var/lib/jenkins/workspace/registry/ca/certs/ca.crt.pem' ca_cert_path: '/var/lib/jenkins/workspace/registry/ca/certs/ca.crt.pem'

View file

@ -1,7 +1,9 @@
dir_mode: script dir_mode: script
dir: ../../log dir: ../../log/que
multiple: true multiple: true
backtrace: true backtrace: true
monitor: true monitor: true
ontop: false ontop: false
app_name: 'que' app_name: 'que'
user: <%= ENV['QUE_USER'] || 'registry' %>
group: <%= ENV['QUE_GROUP'] || ENV['QUE_USER'] || 'registry' %>

View file

@ -21,3 +21,20 @@ api_log_test:
registrant_write_test: registrant_write_test:
<<: *default <<: *default
database: registry_test database: registry_test
# only for testing assets
production:
<<: *default
database: registry_test
whois_test:
<<: *default
database: registry_whois_test
api_log_test:
<<: *default
database: registry_api_log_test
registrant_write_test:
<<: *default
database: registry_test

View file

@ -11,7 +11,7 @@ require 'mina/rbenv' # for rbenv support. (http://rbenv.org)
# branch - Branch name to deploy. (needed by mina/git) # branch - Branch name to deploy. (needed by mina/git)
# alpha branch, all interfaces unified # alpha branch, all interfaces unified
set :domain, 'registry-st' set :domain, 'registry'
set :deploy_to, '$HOME/registry' set :deploy_to, '$HOME/registry'
set :repository, 'https://github.com/domify/registry' # dev repo set :repository, 'https://github.com/domify/registry' # dev repo
set :branch, 'master' set :branch, 'master'
@ -20,7 +20,7 @@ set :que_restart, true
# alpha branch, only use for heavy debugging # alpha branch, only use for heavy debugging
task :epp do task :epp do
set :domain, 'registry-st' set :domain, 'registry'
set :deploy_to, '$HOME/epp' set :deploy_to, '$HOME/epp'
set :repository, 'https://github.com/domify/registry' # dev repo set :repository, 'https://github.com/domify/registry' # dev repo
set :branch, 'master' set :branch, 'master'
@ -30,7 +30,7 @@ end
# alpha branch, only use for heavy debugging # alpha branch, only use for heavy debugging
task :registrar do task :registrar do
set :domain, 'registry-st' set :domain, 'registry'
set :deploy_to, '$HOME/registrar' set :deploy_to, '$HOME/registrar'
set :repository, 'https://github.com/domify/registry' # dev repo set :repository, 'https://github.com/domify/registry' # dev repo
set :branch, 'master' set :branch, 'master'
@ -40,7 +40,7 @@ end
# alpha branch, only use for heavy debugging # alpha branch, only use for heavy debugging
task :registrant do task :registrant do
set :domain, 'registry-st' set :domain, 'registryt'
set :deploy_to, '$HOME/registrant' set :deploy_to, '$HOME/registrant'
set :repository, 'https://github.com/domify/registry' # dev repo set :repository, 'https://github.com/domify/registry' # dev repo
set :branch, 'master' set :branch, 'master'
@ -138,7 +138,8 @@ set :shared_paths, [
'public/system', 'public/system',
'export/zonefiles', 'export/zonefiles',
'import/bank_statements', 'import/bank_statements',
'import/legal_documents' 'import/legal_documents',
'tmp/pids'
] ]
# Optional settings: # Optional settings:
@ -180,6 +181,9 @@ task setup: :environment do
queue! %(mkdir -p "#{deploy_to}/shared/import/legal_documents") queue! %(mkdir -p "#{deploy_to}/shared/import/legal_documents")
queue! %(chmod g+rx,u+rwx "#{deploy_to}/shared/import/legal_documents") queue! %(chmod g+rx,u+rwx "#{deploy_to}/shared/import/legal_documents")
queue! %(mkdir -p "#{deploy_to}/shared/log/que")
queue! %(chmod g+rx,u+rwx "#{deploy_to}/shared/log/que")
queue! %(touch "#{deploy_to}/shared/config/database.yml") queue! %(touch "#{deploy_to}/shared/config/database.yml")
deploy do deploy do
invoke :'git:clone' invoke :'git:clone'
@ -199,30 +203,22 @@ task deploy: :environment do
# instance of your project. # instance of your project.
invoke :'git:clone' invoke :'git:clone'
invoke :load_commit_hash invoke :load_commit_hash
# TEMP until all servers are updated
queue! %(mkdir -p "#{deploy_to}/shared/log/que")
queue! %(chmod g+rx,u+rwx "#{deploy_to}/shared/log/que")
invoke :'deploy:link_shared_paths' invoke :'deploy:link_shared_paths'
invoke :'bundle:install' invoke :'bundle:install'
invoke :'rails:db_migrate' invoke :'rails:db_migrate'
to :launch do to :launch do
invoke :restart invoke :restart
invoke :'deploy:cleanup' invoke :'deploy:cleanup'
queue! "QUE_WORKER_COUNT=1 #{rake} daemon:que:restart" if que_restart invoke :que_restart if que_restart
end end
end end
end end
desc 'Rolls back the latest release'
task rollback: :environment do
queue! %(echo "-----> Rolling back to previous release for instance: #{domain}")
queue %(ls "#{deploy_to}/releases" -Art | sort | tail -n 2 | head -n 1)
queue! %(
ls -Art "#{deploy_to}/releases" | sort | tail -n 2 | head -n 1 |
xargs -I active ln -nfs "#{deploy_to}/releases/active" "#{deploy_to}/current"
)
to :launch do
invoke :restart
end
end
desc 'Loads current commit hash' desc 'Loads current commit hash'
task load_commit_hash: :environment do task load_commit_hash: :environment do
queue! %( queue! %(
@ -236,6 +232,11 @@ task restart: :environment do
queue "mkdir -p #{deploy_to}/current/tmp; touch #{deploy_to}/current/tmp/restart.txt" queue "mkdir -p #{deploy_to}/current/tmp; touch #{deploy_to}/current/tmp/restart.txt"
end end
desc 'Restart que server'
task que_restart: :environment do
queue "/etc/init.d/que restart"
end
namespace :cron do namespace :cron do
desc 'Setup cron tasks.' desc 'Setup cron tasks.'
task setup: :environment do task setup: :environment do

View file

@ -44,7 +44,7 @@ Rails.application.configure do
# The available log levels are: :debug, :info, :warn, :error, :fatal, and :unknown, # The available log levels are: :debug, :info, :warn, :error, :fatal, and :unknown,
# corresponding to the log level numbers from 0 up to 5 respectively # corresponding to the log level numbers from 0 up to 5 respectively
config.log_level = :fatal config.log_level = :info
# for finding database optimization # for finding database optimization
config.after_initialize do config.after_initialize do

View file

@ -0,0 +1,14 @@
# EIS custom rack hack in order to enable test external interfaces EPP/REPP inside webserver network
# rubocop:disable Metrics/LineLength
module Rack
class Request
def trusted_proxy?(ip)
if ENV['eis_trusted_proxies']
ENV['eis_trusted_proxies'].split(',').map(&:strip).include?(ip)
else
ip =~ /\A127\.0\.0\.1\Z|\A(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\.|\A::1\Z|\Afd[0-9a-f]{2}:.+|\Alocalhost\Z|\Aunix\Z|\Aunix:/i
end
end
end
end
# rubocop:enable Metrics/LineLength

View file

@ -7,7 +7,7 @@ required = %w(
ca_cert_path ca_cert_path
ca_key_path ca_key_path
ca_key_password ca_key_password
webclient_ip webclient_ips
legal_documents_dir legal_documents_dir
bank_statement_import_dir bank_statement_import_dir
time_zone time_zone

View file

@ -50,6 +50,7 @@ if con.present? && con.table_exists?('settings')
Setting.save_default(:registry_vat_prc, 0.2) Setting.save_default(:registry_vat_prc, 0.2)
Setting.save_default(:registry_iban, 'EE557700771000598731') Setting.save_default(:registry_iban, 'EE557700771000598731')
Setting.save_default(:registry_bank, 'LHV Pank') Setting.save_default(:registry_bank, 'LHV Pank')
Setting.save_default(:registry_bank_code, '689')
Setting.save_default(:registry_swift, 'LHVBEE22') Setting.save_default(:registry_swift, 'LHVBEE22')
Setting.save_default(:registry_invoice_contact, 'Martti Õigus') Setting.save_default(:registry_invoice_contact, 'Martti Õigus')
end end

View file

@ -36,6 +36,7 @@ en:
attributes: attributes:
code: code:
blank: "Required parameter missing - code" blank: "Required parameter missing - code"
too_long_contact_code: "Contact code is too long, max 100 characters"
name: name:
blank: "Required parameter missing - name" blank: "Required parameter missing - name"
phone: phone:
@ -51,6 +52,8 @@ en:
invalid_country_code: "Ident country code is not valid, should be in ISO_3166-1 alpha 2 format" invalid_country_code: "Ident country code is not valid, should be in ISO_3166-1 alpha 2 format"
domains: domains:
exist: 'Object association prohibits operation' exist: 'Object association prohibits operation'
statuses:
not_uniq: 'not uniq'
epp_domain: &epp_domain_ar_attributes epp_domain: &epp_domain_ar_attributes
attributes: attributes:
@ -256,7 +259,7 @@ en:
invalid_type: 'PostalInfo type is invalid' invalid_type: 'PostalInfo type is invalid'
unimplemented_command: 'Unimplemented command' unimplemented_command: 'Unimplemented command'
domain_exists_but_belongs_to_other_registrar: 'Domain exists but belongs to other registrar' domain_exists_but_belongs_to_other_registrar: 'Domain exists but belongs to other registrar'
required_attribute_missing: Required attributes missing required_ident_attribute_missing: "Required ident attribute missing: %{key}"
code: 'Code' code: 'Code'
value: 'Value' value: 'Value'
@ -832,7 +835,7 @@ en:
unset_force_delete: 'Unset force delete' unset_force_delete: 'Unset force delete'
domain_expiring: 'Domain expiring' domain_expiring: 'Domain expiring'
domain_validation_rules: 'Domain validation rules' domain_validation_rules: 'Domain validation rules'
bank_statement_desc: 'Import file row will match only when matching following attributes: <b><br>ref number<br>payment amount<br>invoice number (the very first number in comment field)</b>.' bank_statement_desc: 'Import file row will match only when matching following attributes: <b><br>ref number<br>payment amount<br>invoice number (the first numerical value in comment field)</b>.'
create_bank_statement: 'Create bank statement' create_bank_statement: 'Create bank statement'
create_bank_transaction: 'Create bank transaction' create_bank_transaction: 'Create bank transaction'
create_new_invoice: 'Create new invoice' create_new_invoice: 'Create new invoice'
@ -869,4 +872,8 @@ en:
reserved_pw: 'Reserved pw' reserved_pw: 'Reserved pw'
no_transfers_found: 'No transfers found' no_transfers_found: 'No transfers found'
parameter_value_range_error: 'Parameter value range error: %{key}' parameter_value_range_error: 'Parameter value range error: %{key}'
payment_received: 'Payment received'
domain_registrant_updated: 'Domeeni %{name} registreerija vahetus teostatud / Registrant change of %{name} has been finished.' domain_registrant_updated: 'Domeeni %{name} registreerija vahetus teostatud / Registrant change of %{name} has been finished.'
api_user_not_found: 'API user not found'
domain_already_belongs_to_the_querying_registrar: 'Domain already belongs to the querying registrar'
notes: Notes

View file

@ -0,0 +1,15 @@
class RefactorContactStatuses < ActiveRecord::Migration
def self.up
Contact.find_each do |contact|
statuses = []
contact.depricated_statuses.each do |ds|
statuses << ds.value
end
contact.update_column('statuses', statuses)
end
end
def self.down
raise ActiveRecord::IrreversibleMigration
end
end

View file

@ -0,0 +1,5 @@
class AddStatusesToContact < ActiveRecord::Migration
def change
add_column :contacts, :statuses, :string, array: true
end
end

View file

@ -0,0 +1,6 @@
class AddContactAndDomainStatusNotes < ActiveRecord::Migration
def change
add_column :contacts, :status_notes, :hstore
add_column :domains, :status_notes, :hstore
end
end

View file

@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150713113436) do ActiveRecord::Schema.define(version: 20150722071128) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -200,6 +200,7 @@ ActiveRecord::Schema.define(version: 20150713113436) do
t.string "state" t.string "state"
t.integer "legacy_id" t.integer "legacy_id"
t.string "statuses", array: true t.string "statuses", array: true
t.hstore "status_notes"
end end
add_index "contacts", ["code"], name: "index_contacts_on_code", using: :btree add_index "contacts", ["code"], name: "index_contacts_on_code", using: :btree
@ -215,12 +216,6 @@ ActiveRecord::Schema.define(version: 20150713113436) do
t.string "updator_str" t.string "updator_str"
end end
create_table "data_migrations", id: false, force: :cascade do |t|
t.string "version", null: false
end
add_index "data_migrations", ["version"], name: "unique_data_migrations", unique: true, using: :btree
create_table "delegation_signers", force: :cascade do |t| create_table "delegation_signers", force: :cascade do |t|
t.integer "domain_id" t.integer "domain_id"
t.string "key_tag" t.string "key_tag"
@ -327,6 +322,7 @@ ActiveRecord::Schema.define(version: 20150713113436) do
t.datetime "force_delete_at" t.datetime "force_delete_at"
t.string "statuses", array: true t.string "statuses", array: true
t.boolean "reserved", default: false t.boolean "reserved", default: false
t.hstore "status_notes"
end end
add_index "domains", ["delete_at"], name: "index_domains_on_delete_at", using: :btree add_index "domains", ["delete_at"], name: "index_domains_on_delete_at", using: :btree

View file

@ -632,7 +632,8 @@ CREATE TABLE contacts (
country_code character varying, country_code character varying,
state character varying, state character varying,
legacy_id integer, legacy_id integer,
statuses character varying[] statuses character varying[],
status_notes hstore
); );
@ -689,15 +690,6 @@ CREATE SEQUENCE countries_id_seq
ALTER SEQUENCE countries_id_seq OWNED BY countries.id; ALTER SEQUENCE countries_id_seq OWNED BY countries.id;
--
-- Name: data_migrations; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
CREATE TABLE data_migrations (
version character varying NOT NULL
);
-- --
-- Name: delegation_signers; Type: TABLE; Schema: public; Owner: -; Tablespace: -- Name: delegation_signers; Type: TABLE; Schema: public; Owner: -; Tablespace:
-- --
@ -945,7 +937,8 @@ CREATE TABLE domains (
pending_json json, pending_json json,
force_delete_at timestamp without time zone, force_delete_at timestamp without time zone,
statuses character varying[], statuses character varying[],
reserved boolean DEFAULT false reserved boolean DEFAULT false,
status_notes hstore
); );
@ -4519,13 +4512,6 @@ CREATE INDEX index_whois_records_on_domain_id ON whois_records USING btree (doma
CREATE INDEX index_whois_records_on_registrar_id ON whois_records USING btree (registrar_id); CREATE INDEX index_whois_records_on_registrar_id ON whois_records USING btree (registrar_id);
--
-- Name: unique_data_migrations; Type: INDEX; Schema: public; Owner: -; Tablespace:
--
CREATE UNIQUE INDEX unique_data_migrations ON data_migrations USING btree (version);
-- --
-- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: -; Tablespace: -- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: -; Tablespace:
-- --
@ -4861,10 +4847,6 @@ INSERT INTO schema_migrations (version) VALUES ('20150522164020');
INSERT INTO schema_migrations (version) VALUES ('20150525075550'); 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 ('20150603141054');
INSERT INTO schema_migrations (version) VALUES ('20150603141549'); INSERT INTO schema_migrations (version) VALUES ('20150603141549');
@ -4873,12 +4855,8 @@ INSERT INTO schema_migrations (version) VALUES ('20150603211318');
INSERT INTO schema_migrations (version) VALUES ('20150603212659'); 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 ('20150609103333');
INSERT INTO schema_migrations (version) VALUES ('20150610111019');
INSERT INTO schema_migrations (version) VALUES ('20150610112238'); INSERT INTO schema_migrations (version) VALUES ('20150610112238');
INSERT INTO schema_migrations (version) VALUES ('20150610144547'); INSERT INTO schema_migrations (version) VALUES ('20150610144547');
@ -4887,8 +4865,6 @@ INSERT INTO schema_migrations (version) VALUES ('20150611124920');
INSERT INTO schema_migrations (version) VALUES ('20150612123111'); 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 ('20150701074344');
INSERT INTO schema_migrations (version) VALUES ('20150703084632'); INSERT INTO schema_migrations (version) VALUES ('20150703084632');
@ -4897,8 +4873,6 @@ INSERT INTO schema_migrations (version) VALUES ('20150706091724');
INSERT INTO schema_migrations (version) VALUES ('20150707103241'); 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 ('20150707104937');
INSERT INTO schema_migrations (version) VALUES ('20150707154543'); INSERT INTO schema_migrations (version) VALUES ('20150707154543');
@ -4907,3 +4881,5 @@ INSERT INTO schema_migrations (version) VALUES ('20150709092549');
INSERT INTO schema_migrations (version) VALUES ('20150713113436'); INSERT INTO schema_migrations (version) VALUES ('20150713113436');
INSERT INTO schema_migrations (version) VALUES ('20150722071128');

View file

@ -24,7 +24,8 @@ Deploy overview: (database schema should be loaded and seeds should be present)
git clone git@github.com:internetee/registry.git git clone git@github.com:internetee/registry.git
cd registry cd registry
rbenv local 2.2.2 # more info about rbenv at debian doc rbenv local 2.2.2 # more info about rbenv at debian doc
gem install mina gem install mina # or any other deployment tool
cp config/deploy-example.rb config/deploy.rb # and edit it
mina pr setup # one time, only creates missing directories mina pr setup # one time, only creates missing directories
ssh registry ssh registry
@ -37,15 +38,17 @@ Deploy overview: (database schema should be loaded and seeds should be present)
vi /etc/apache2/sites-enabled/epp.conf # add epp conf, restart apache vi /etc/apache2/sites-enabled/epp.conf # add epp conf, restart apache
exit exit
# at your local machine # at your local machine
mina pr deploy # this is command you use in every application code update mina pr deploy # for new update using mina tool as example
### Deploy script setup ### Deploy script setup
We recommend [Mina](https://github.com/mina-deploy/mina) instead of Capistrano for deployment. We recommend [Mina](https://github.com/mina-deploy/mina) instead of Capistrano or other tools for deployment.
All deploy code locates at config/deploy.rb file. All deploy code locates at config/deploy.rb, please copy content from example file and edit it.
cp config/deploy-example.rb config/deploy.rb # and edit it
First add shortcuts to your local machine ssh config file, First add shortcuts to your local machine ssh config file,

View file

@ -100,7 +100,7 @@ Configure registry registry/shared/config/application.yml to match the CA settin
Configure registry epp registry-epp/shared/config/application.yml: Configure registry epp registry-epp/shared/config/application.yml:
webclient_ip: '54.154.91.240' webclient_ips: '54.154.91.240'
Configure EPP port 700 virtual host: Configure EPP port 700 virtual host:
@ -215,7 +215,7 @@ After deploy, in rails console:
Certificate.update_crl Certificate.update_crl
Update cron: Update cron (mina tool example, when installed correctly):
mina cron:setup mina cron:setup

File diff suppressed because it is too large Load diff

View file

@ -13,7 +13,8 @@ Contact Mapping protocol short version:
----------------------- ------- ----------------- ----------------------- ------- -----------------
<create> 1 <create> 1
<contact:create> 1 Attribute: xmlns:contact="https://raw.githubusercontent.com/internetee/registry/alpha/doc/schemas/contact-eis-1.0.xsd" <contact:create> 1 Attribute: xmlns:contact="https://raw.githubusercontent.com/internetee/registry/alpha/doc/schemas/contact-eis-1.0.xsd"
<contact:id> 0-1 Contact id, optional, generated automatically if missing <contact:id> 0-1 Contact id, optional, string, no spaces, max 100 characters,
generated automatically if missing
<contact:postalInfo> 1 Postal information container <contact:postalInfo> 1 Postal information container
<contact:name> 1 Full name of the contact <contact:name> 1 Full name of the contact
<contact:org> 0 Org is not supported and must be blank or missing <contact:org> 0 Org is not supported and must be blank or missing

View file

@ -18,6 +18,7 @@ Domain name mapping protocol short version:
<domain:period> 0-1 Registration period for domain. <domain:period> 0-1 Registration period for domain.
Must add up to 1 / 2 / 3 years. Must add up to 1 / 2 / 3 years.
Attribute: unit="y/m/d" Attribute: unit="y/m/d"
Default is 1 year.
<domain:registrant> 1 Contact reference to the registrant <domain:registrant> 1 Contact reference to the registrant
Attribute: Attribute:
"verified" # optional, allowed values 'yes', 'no' "verified" # optional, allowed values 'yes', 'no'
@ -129,8 +130,9 @@ Domain name mapping protocol short version:
<domain:renew> 1 Attribute: xmlns:domain="https://raw.githubusercontent.com/internetee/registry/alpha/doc/schemas/domain-eis-1.0.xsd" <domain:renew> 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:name> 1 Domain name. Can contain unicode characters.
<domain:curExpDate> 1 Current expiry date (ISO8601 format) <domain:curExpDate> 1 Current expiry date (ISO8601 format)
<domain:period> 1 Registration period for domain. <domain:period> 0-1 Registration period for domain.
Must add up to 1 / 2 / 3 years. Attribute: unit="y/m/d" Must add up to 1 / 2 / 3 years. Attribute: unit="y/m/d"
Default value is 1 year.
<extension> 0-1 <extension> 0-1
<eis:extdata> 0-1 Attribute: xmlns:eis="https://raw.githubusercontent.com/internetee/registry/alpha/doc/schemas/eis-1.0.xsd" <eis:extdata> 0-1 Attribute: xmlns:eis="https://raw.githubusercontent.com/internetee/registry/alpha/doc/schemas/eis-1.0.xsd"
<eis:legalDocument> 0-1 Base64 encoded document. <eis:legalDocument> 0-1 Base64 encoded document.

View file

@ -22,9 +22,15 @@ Installation at deployed server:
sudo /etc/init.d/que start # for manual start sudo /etc/init.d/que start # for manual start
sudo update-rc.d que defaults # for start in server boot sudo update-rc.d que defaults # for start in server boot
# Debugging PID files
---------
You can run que manually as well: All pid files are at log/que directory.
Debugging
---------
You can run que manually as well for debugging:
cd /home/registry/registry/current cd /home/registry/registry/current

View file

@ -11,38 +11,35 @@
set -u set -u
set -e set -e
# ### CHANGES
# Change these to match your server:
#
# Make sure that all paths are correct.
#
APP_HOME="/home/registry/registry" APP_HOME="/home/registry/registry"
APP_ROOT="$APP_HOME/current" APP_ROOT="$APP_HOME/current"
QUE_USER=registry # or use some other unprivileged system user QUE_USER=registry # or use some other unprivileged OS user what your registry servers uses
RAILS_ENV=production RAILS_ENV=production
RUBY_BUNDLE_PATH=/home/$QUE_USER/.rbenv/shims/bundle RUBY_BUNDLE=/home/$QUE_USER/.rbenv/shims/bundle
QUE_INSTANCES=1 # or as many really needed based real load QUE_INSTANCES=1 # or as many really needed based on real load info
### END OF CHANGES
cd $APP_ROOT || exit 1 cd $APP_ROOT || exit 1
case ${1-help} in case ${1-help} in
status) status)
cd $APP_ROOT && RAILS_ENV=$RAILS_ENV $RUBY_BUNDLE_PATH exec lib/daemons/que_ctl status cd $APP_ROOT && RAILS_ENV=$RAILS_ENV $RUBY_BUNDLE exec lib/daemons/que_ctl status
;; ;;
start) start)
echo "$1 que monitor and server" echo "$1 que monitor and server"
for i in `seq 1 $QUE_INSTANCES`; do for i in `seq 1 $QUE_INSTANCES`; do
cd $APP_ROOT && QUE_WORKER_COUNT=1 RAILS_ENV=$RAILS_ENV $RUBY_BUNDLE_PATH exec rake daemon:que:start cd $APP_ROOT && QUE_WORKER_COUNT=1 RAILS_ENV=$RAILS_ENV QUE_USER=$QUE_USER $RUBY_BUNDLE exec rake daemon:que:start
echo '.' echo 'que instance started'
done done
;; ;;
stop) stop)
echo "$1 que monitor and server" echo "$1 que monitor and server"
cd $APP_ROOT && RAILS_ENV=$RAILS_ENV $RUBY_BUNDLE_PATH exec lib/daemons/que_ctl stop cd $APP_ROOT && RAILS_ENV=$RAILS_ENV $RUBY_BUNDLE exec lib/daemons/que_ctl stop
;; ;;
restart) restart)
echo "$1 que monitor and server" echo "$1 que monitor and server"
cd $APP_ROOT && RAILS_ENV=$RAILS_ENV $RUBY_BUNDLE_PATH exec rake daemon:que:restart cd $APP_ROOT && RAILS_ENV=$RAILS_ENV QUE_USER=$QUE_USER $RUBY_BUNDLE exec rake daemon:que:restart
;; ;;
*) *)
echo >&2 "Usage: $0 <status|start|stop|restart>" echo >&2 "Usage: $0 <status|start|stop|restart>"

View file

@ -26,7 +26,7 @@ Que.mode = :async
# the rake task in tasks/safe_shutdown.rb. # the rake task in tasks/safe_shutdown.rb.
stop = false stop = false
%w( INT TERM ).each do |signal| %w( INT ).each do |signal|
trap(signal) { stop = true } trap(signal) { stop = true }
end end

View file

@ -12,3 +12,7 @@ namespace :assets do
end end
end end
end end
task as: :environment do
system('RAILS_ENV=production rake assets:precompile')
end

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -176,6 +176,19 @@ describe 'EPP Contact', epp: true do
response[:result_code].should == '2005' response[:result_code].should == '2005'
end end
it 'should not strange characters in custom code' do
response = create_request({ id: { value: '33&$@@' } })
response[:msg].should == 'is invalid [code]'
response[:result_code].should == '2005'
end
it 'should not strange characters in custom code' do
long_str = 'a' * 1000
response = create_request({ id: { value: long_str } })
response[:msg].should == 'Contact code is too long, max 100 characters [code]'
response[:result_code].should == '2005'
end
it 'should not saves ident type with wrong country code' do it 'should not saves ident type with wrong country code' do
extension = { extension = {
ident: { ident: {
@ -189,6 +202,31 @@ describe 'EPP Contact', epp: true do
response[:result_code].should == '2005' response[:result_code].should == '2005'
end end
it 'should return country missing' do
extension = {
ident: {
value: '1990-22-12',
attrs: { type: 'birthday' }
}
}
response = create_request({}, extension, validate_input: false)
response[:msg].should ==
'Required ident attribute missing: cc'
response[:result_code].should == '2003'
end
it 'should return country missing' do
extension = {
ident: {
value: '1990-22-12'
}
}
response = create_request({}, extension, validate_input: false)
response[:msg].should ==
'Required ident attribute missing: type'
response[:result_code].should == '2003'
end
it 'should add registrar prefix for code when legacy prefix present' do it 'should add registrar prefix for code when legacy prefix present' do
response = create_request({ id: { value: 'CID:FIRST0:abc:ABC:NEW:12345' } }) response = create_request({ id: { value: 'CID:FIRST0:abc:ABC:NEW:12345' } })
response[:msg].should == 'Command completed successfully' response[:msg].should == 'Command completed successfully'

View file

@ -435,6 +435,24 @@ describe 'EPP Domain', epp: true do
a.activity_type = AccountActivity::CREATE a.activity_type = AccountActivity::CREATE
end end
it 'creates a domain without period' do
old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count
xml = domain_create_xml(period: nil)
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(1.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('10.0')
a.activity_type = AccountActivity::CREATE
a.log_pricelist_id.should == @pricelist_reg_1_year.id
end
it 'does not create a domain with invalid period' do it 'does not create a domain with invalid period' do
old_balance = @registrar1.balance old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count old_activities = @registrar1.cash_account.account_activities.count
@ -450,6 +468,24 @@ describe 'EPP Domain', epp: true do
@registrar1.cash_account.account_activities.count.should == old_activities @registrar1.cash_account.account_activities.count.should == old_activities
end end
it 'does not create a domain with invalid period unit' do
xml = domain_create_xml({
period: { value: '1', attrs: { unit: '' } }
})
response = epp_plain_request(xml, validate_input: false)
response[:results][0][:msg].should == 'Attribute is invalid: unit'
response[:results][0][:result_code].should == '2306'
xml = domain_create_xml({
period: { value: '1', attrs: { unit: 'bla' } }
})
response = epp_plain_request(xml, validate_input: false)
response[:results][0][:msg].should == 'Attribute is invalid: unit'
response[:results][0][:result_code].should == '2306'
end
it 'creates a domain with multiple dnskeys' do it 'creates a domain with multiple dnskeys' do
xml = domain_create_xml({}, { xml = domain_create_xml({}, {
_anonymus: [ _anonymus: [
@ -2185,16 +2221,14 @@ describe 'EPP Domain', epp: true do
### RENEW ### ### RENEW ###
it 'renews a domain' do it 'renews a domain' do
Setting.days_to_renew_domain_before_expire = 0
old_balance = @registrar1.balance old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count old_activities = @registrar1.cash_account.account_activities.count
domain.valid_to = Time.zone.now.to_date + 10.days exp_date = domain.valid_to
domain.save
exp_date = domain.valid_to.to_date
xml = @epp_xml.domain.renew( xml = @epp_xml.domain.renew(
name: { value: domain.name }, name: { value: domain.name },
curExpDate: { value: exp_date.to_s }, curExpDate: { value: exp_date.to_date.to_s },
period: { value: '1', attrs: { unit: 'y' } } period: { value: '1', attrs: { unit: 'y' } }
) )
@ -2204,9 +2238,16 @@ describe 'EPP Domain', epp: true do
ex_date = response[:parsed].css('renData exDate').text ex_date = response[:parsed].css('renData exDate').text
name = response[:parsed].css('renData name').text name = response[:parsed].css('renData name').text
ex_date.should == "#{(exp_date + 1.year)}T00:00:00Z" ex_date.should == "#{(exp_date + 1.year).to_s(:iso8601)}"
name.should == domain.name name.should == domain.name
domain.reload
domain.valid_to.should be_within(1).of(exp_date + 1.year)
domain.outzone_at.should be_within(1).of(exp_date + 1.year + Setting.expire_warning_period.days)
domain.delete_at.should be_within(1).of(
exp_date + 1.year + Setting.expire_warning_period.days + Setting.redemption_grace_period.days
)
@registrar1.balance.should == old_balance - 15.0 @registrar1.balance.should == old_balance - 15.0
@registrar1.cash_account.account_activities.count.should == old_activities + 1 @registrar1.cash_account.account_activities.count.should == old_activities + 1
a = @registrar1.cash_account.account_activities.last a = @registrar1.cash_account.account_activities.last
@ -2214,6 +2255,93 @@ describe 'EPP Domain', epp: true do
a.sum.should == -BigDecimal.new('15.0') a.sum.should == -BigDecimal.new('15.0')
a.activity_type = AccountActivity::RENEW a.activity_type = AccountActivity::RENEW
a.log_pricelist_id.should == @pricelist_renew_1_year.id a.log_pricelist_id.should == @pricelist_renew_1_year.id
Setting.days_to_renew_domain_before_expire = 90
end
it 'renews a domain when outzone_at or delete_at is nil for some reason' do
Setting.days_to_renew_domain_before_expire = 0
domain.outzone_at = nil
domain.delete_at = nil
domain.save
exp_date = domain.valid_to
xml = @epp_xml.domain.renew(
name: { value: domain.name },
curExpDate: { value: exp_date.to_date.to_s },
period: { value: '1', attrs: { unit: 'y' } }
)
response = epp_plain_request(xml)
response[:results][0][:msg].should == 'Command completed successfully'
response[:results][0][:result_code].should == '1000'
Setting.days_to_renew_domain_before_expire = 90
end
it 'renews a domain with no period specified' do
Setting.days_to_renew_domain_before_expire = 0
old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count
exp_date = domain.valid_to
xml = @epp_xml.domain.renew(
name: { value: domain.name },
curExpDate: { value: exp_date.to_date.to_s },
period: nil
)
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 + 1.year).to_s(:iso8601)}"
name.should == domain.name
domain.reload
domain.valid_to.should be_within(1).of(exp_date + 1.year)
domain.outzone_at.should be_within(1).of(exp_date + 1.year + Setting.expire_warning_period.days)
domain.delete_at.should be_within(1).of(
exp_date + 1.year + Setting.expire_warning_period.days + Setting.redemption_grace_period.days
)
@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
Setting.days_to_renew_domain_before_expire = 90
end
it 'does not renew domain with invalid period' do
Setting.days_to_renew_domain_before_expire = 0
exp_date = domain.valid_to
xml = @epp_xml.domain.renew(
name: { value: domain.name },
curExpDate: { value: exp_date.to_date.to_s },
period: { value: '1', attrs: { unit: '' } }
)
response = epp_plain_request(xml, validate_input: false)
response[:results][0][:msg].should == 'Attribute is invalid: unit'
response[:results][0][:result_code].should == '2306'
xml = @epp_xml.domain.renew(
name: { value: domain.name },
curExpDate: { value: exp_date.to_date.to_s },
period: { value: '1', attrs: { unit: 'bla' } }
)
response = epp_plain_request(xml, validate_input: false)
response[:results][0][:msg].should == 'Attribute is invalid: unit'
response[:results][0][:result_code].should == '2306'
Setting.days_to_renew_domain_before_expire = 90
end end
it 'renews a domain with 2 year period' do it 'renews a domain with 2 year period' do

View file

@ -28,6 +28,11 @@ describe 'EPP Session', epp: true do
response[:msg].should == 'Authentication error; server closing connection (API user not found)' response[:msg].should == 'Authentication error; server closing connection (API user not found)'
response[:result_code].should == '2501' response[:result_code].should == '2501'
response[:clTRID].should == 'ABC-12345' response[:clTRID].should == 'ABC-12345'
log = ApiLog::EppLog.last
log.request_command.should == 'login'
log.request_successful.should == false
log.api_user_name.should == 'api-public'
end end
it 'does not log in with inactive user' do it 'does not log in with inactive user' do
@ -38,6 +43,11 @@ describe 'EPP Session', epp: true do
response = epp_plain_request(inactive) response = epp_plain_request(inactive)
response[:msg].should == 'Authentication error; server closing connection (API user is not active)' response[:msg].should == 'Authentication error; server closing connection (API user is not active)'
response[:result_code].should == '2501' response[:result_code].should == '2501'
log = ApiLog::EppLog.last
log.request_command.should == 'login'
log.request_successful.should == false
log.api_user_name.should == '2-api-inactive-user'
end end
it 'prohibits further actions unless logged in' do it 'prohibits further actions unless logged in' do
@ -61,6 +71,11 @@ describe 'EPP Session', epp: true do
response[:msg].should == 'Parameter value policy error. Allowed only Latin characters.' response[:msg].should == 'Parameter value policy error. Allowed only Latin characters.'
response[:result_code].should == '2306' response[:result_code].should == '2306'
response[:clTRID].should == 'ABC-12345' response[:clTRID].should == 'ABC-12345'
log = ApiLog::EppLog.last
log.request_command.should == 'login'
log.request_successful.should == false
log.api_user_name.should == 'api-public'
end end
context 'with valid user' do context 'with valid user' do

View file

@ -59,4 +59,52 @@ feature 'Invoice', type: :feature do
response_headers['Content-Type'].should == 'application/pdf' response_headers['Content-Type'].should == 'application/pdf'
response_headers['Content-Disposition'].should == "attachment; filename=\"#{@invoice.pdf_name}\"" response_headers['Content-Disposition'].should == "attachment; filename=\"#{@invoice.pdf_name}\""
end end
it 'should create bank statement and transaction for invoice' do
r = Fabricate(:registrar, reference_no: 'RF7086666663')
invoice = r.issue_prepayment_invoice(200, 'add some money')
visit '/admin/invoices'
click_link invoice.to_s
page.should have_content('Unpaid')
click_link 'Payment received'
paid_at = Time.zone.now
find_field('Bank code').value.should == '689'
find_field('Iban').value.should == 'EE557700771000598731'
find_field('Description').value.should == invoice.to_s
find_field('Sum').value.should == invoice.sum.to_s
find_field('Currency').value.should == 'EUR'
find_field('Reference no').value.should == invoice.reference_no
find_field('Paid at').value.should == paid_at.to_date.to_s
click_button 'Save'
page.should have_content('Record created')
page.should have_content('689')
page.should have_content('EE557700771000598731')
page.should have_content('Not binded', count: 2)
page.should have_content(invoice.sum.to_s)
page.should have_content('EUR')
click_link 'Bind invoices'
page.should have_content('Invoices were fully binded')
page.should have_content('Fully binded')
page.should have_content('Binded')
click_link I18n.l(paid_at, format: :date_long)
page.should have_content('Binded')
page.should have_content(invoice.to_s)
page.should have_content(invoice.sum.to_s)
page.should have_content(invoice.reference_no)
page.should have_content(I18n.l(paid_at, format: :date_long))
click_link(invoice.to_s)
page.should_not have_content('Unpaid')
page.should_not have_content('Payment received')
end
end end

View file

@ -97,7 +97,13 @@ describe Contact do
it 'should not accept long code' do it 'should not accept long code' do
@contact.code = 'verylongcode' * 100 @contact.code = 'verylongcode' * 100
@contact.valid? @contact.valid?
@contact.errors[:code].should == ['is too long (maximum is 100 characters)'] @contact.errors[:code].should == ['Contact code is too long, max 100 characters']
end
it 'should not allow double status' do
@contact.statuses = ['ok', 'ok']
@contact.valid?
@contact.errors[:statuses].should == ['not uniq']
end end
it 'should have no related domain descriptions' do it 'should have no related domain descriptions' do
@ -154,17 +160,36 @@ describe Contact do
end end
it 'should have ok status by default' do it 'should have ok status by default' do
@contact.statuses.size.should == 1 @contact.statuses.should == %w(ok)
@contact.statuses.first.value.should == 'ok' end
it 'should not remove ok status after save' do
@contact.statuses.should == %w(ok)
@contact.save
@contact.statuses.should == %w(ok)
end
it 'should remove ok status when other non linked status present' do
contact = Fabricate(:contact)
contact.statuses = [Contact::SERVER_UPDATE_PROHIBITED]
contact.statuses.should == [Contact::SERVER_UPDATE_PROHIBITED] # temp test
contact.save
contact.statuses.should == [Contact::SERVER_UPDATE_PROHIBITED]
end end
it 'should have linked status when domain' do it 'should have linked status when domain' do
@tech_domain_contact = Fabricate(:tech_domain_contact, contact_id: @contact.id) contact = Fabricate(:contact)
@domain = Fabricate(:domain, tech_domain_contacts: [@tech_domain_contact]) tech_domain_contact = Fabricate(:tech_domain_contact, contact_id: contact.id)
contact = @domain.contacts.first contact.statuses.should == %w(ok)
contact.save domain = Fabricate(:domain, tech_domain_contacts: [tech_domain_contact])
contact.statuses.map(&:value).sort.should == %w(linked ok) contact = domain.contacts.first
contact.save
contact.statuses.sort.should == %w(linked ok)
contact = domain.contacts.second
contact.save
contact.statuses.sort.should == %w(linked ok)
end end
it 'should not have linked status when no domain' do it 'should not have linked status when no domain' do
@ -173,11 +198,11 @@ describe Contact do
contact = @domain.contacts.first contact = @domain.contacts.first
contact.save contact.save
contact.statuses.map(&:value).sort.should == %w(linked ok) contact.statuses.sort.should == %w(linked ok)
contact.domains.first.destroy contact.domains.first.destroy
contact.reload contact.reload
contact.statuses.map(&:value).should == %w(ok) contact.statuses.should == %w(ok)
end end
it 'should have code' do it 'should have code' do
@ -193,6 +218,15 @@ describe Contact do
# contact.statuses.map(&:value).should == %w(ok linked) # contact.statuses.map(&:value).should == %w(ok linked)
end end
it 'should save status notes' do
contact = Fabricate(:contact)
contact.statuses = ['serverDeleteProhibited', 'serverUpdateProhibited']
contact.status_notes_array = [nil, 'update manually turned off']
contact.status_notes['serverDeleteProhibited'].should == nil
contact.status_notes['serverUpdateProhibited'].should == 'update manually turned off'
contact.status_notes['someotherstatus'].should == nil
end
context 'as birthday' do context 'as birthday' do
before do before do
@domain = Fabricate(:domain) @domain = Fabricate(:domain)

View file

@ -2,7 +2,7 @@ require 'rails_helper'
describe Repp::AccountV1 do describe Repp::AccountV1 do
it 'should fail without whitelisted IP' do it 'should fail without whitelisted IP' do
ENV['webclient_ip'] = '192.188.1.1' ENV['webclient_ips'] = '192.188.1.1'
@registrar1 = Fabricate(:registrar, white_ips: [Fabricate(:white_ip_registrar)]) @registrar1 = Fabricate(:registrar, white_ips: [Fabricate(:white_ip_registrar)])
@api_user = Fabricate(:api_user, registrar: @registrar1) @api_user = Fabricate(:api_user, registrar: @registrar1)
@ -11,7 +11,7 @@ describe Repp::AccountV1 do
body = JSON.parse(response.body) body = JSON.parse(response.body)
body['error'].should == 'IP is not whitelisted' body['error'].should == 'IP is not whitelisted'
ENV['webclient_ip'] = '127.0.0.1' ENV['webclient_ips'] = '127.0.0.1'
end end
context 'with valid registrar' do context 'with valid registrar' do

View file

@ -77,5 +77,14 @@ describe Repp::DomainV1 do
# TODO: Log failed API requests too # TODO: Log failed API requests too
end end
it 'returns an error with invalid credentials' do
invalid_user = OpenStruct.new(username: 'bla', password: 'blabala')
get_with_auth '/repp/v1/domains', {}, invalid_user
response.status.should == 401
body = JSON.parse(response.body)
body['error'].should == 'API user not found'
end
end end
end end