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
**.orig
config/initializers/secret_token.rb
config/deploy.rb
config/secrets.yml
config/database.yml
/export

View file

@ -4,6 +4,7 @@ AllCops:
Exclude:
- 'Guardfile'
# stuff generated by AR and rails
- 'config/deploy-example.rb'
- 'db/schema.rb'
- 'db/schema-read-only.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
* 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|
@current_user ||= ApiUser.find_by(username: username, password: password)
if @current_user
true
else
error! I18n.t('api_user_not_found'), 401
end
end
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)
end
@ -20,7 +26,7 @@ module Repp
message = 'Certificate mismatch! Cert common name should be:'
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'
error! "Webclient #{message} #{webclient_cert_name}", 401 if webclient_cert_name != request_name
else

View file

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

View file

@ -16,7 +16,18 @@ class Admin::BankStatementsController < AdminController
end
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
def create
@ -69,6 +80,8 @@ class Admin::BankStatementsController < AdminController
end
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

View file

@ -11,9 +11,38 @@ class Admin::ContactsController < AdminController
render json: Contact.search_by_query(params[:q])
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
def set_contact
@contact = Contact.includes(domains: :registrar).find(params[:id])
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

View file

@ -94,12 +94,26 @@ class Epp::ContactsController < EppController
'postalInfo > addr > pc', 'postalInfo > addr > cc', 'voice', 'email'
)
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?
epp_errors << {
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
# 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
fax_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)
handle_errors(@domain) and return if @domain.errors.any?
@domain.valid?
@domain.errors.delete(:name_dirty) if @domain.errors[:puny_label].any?
handle_errors(@domain) and return if @domain.errors.any?
handle_errors and return unless balance_ok?('create')
@ -94,8 +95,9 @@ class Epp::DomainsController < EppController
def renew
authorize! :renew, @domain
period = params[:parsed_frame].css('period').text
period_unit = params[:parsed_frame].css('period').first['unit']
period_element = params[:parsed_frame].css('period').text
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
success = @domain.renew(
@ -129,10 +131,14 @@ class Epp::DomainsController < EppController
@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'
else
handle_errors(@domain)
epp_errors << {
code: '2303',
msg: I18n.t('no_transfers_found')
}
handle_errors
end
end
@ -154,6 +160,8 @@ class Epp::DomainsController < EppController
@prefix = nil
requires 'extension > extdata > legalDocument'
optional_attribute 'period', 'unit', values: %w(d m y)
status_editing_disabled
end
@ -182,7 +190,9 @@ class Epp::DomainsController < EppController
def validate_renew
@prefix = 'renew > renew >'
requires 'name', 'curExpDate', 'period'
requires 'name', 'curExpDate'
optional_attribute 'period', 'unit', values: %w(d m y)
end
def validate_transfer

View file

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

View file

@ -8,6 +8,18 @@ class EppController < ApplicationController
before_action :latin_only
before_action :validate_request
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
rescue_from StandardError do |e|
@ -28,9 +40,18 @@ class EppController < ApplicationController
}]
end
logger.error e.message
logger.error e.backtrace.join("\n")
# TODO: NOITFY AIRBRAKE / ERRBIT HERE
if Rails.env.test? || Rails.env.development?
# rubocop:disable Rails/Output
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
render_epp_response '/epp/error'
@ -102,7 +123,7 @@ class EppController < ApplicationController
msg: 'handle_errors was executed when there were actually no errors'
}
# 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
end
@ -125,8 +146,13 @@ class EppController < ApplicationController
def latin_only
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)
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
# VALIDATION
@ -212,11 +238,11 @@ class EppController < ApplicationController
end
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
attribute = element[attribute_selector]
return if (attribute && options[:values].include?(attribute)) || !attribute
epp_errors << {

View file

@ -1,4 +1,25 @@
class ApplicationMailer < ActionMailer::Base
default from: 'noreply@internet.ee'
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

View file

@ -1,23 +1,34 @@
class ContactMailer < ApplicationMailer
# rubocop: disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/MethodLength
def email_updated(contact)
unless Rails.env.production?
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
return if delivery_off?(contact)
@contact = contact
emails = []
emails << [@contact.email, @contact.email_was] if @contact.registrant_domains.present?
emails << @contact.domains.map(&:registrant_email) if @contact.domains.present?
emails = emails.uniq
return if whitelist_blocked?(emails)
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
# rubocop: enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/MethodLength
end

View file

@ -1,10 +1,7 @@
class DomainMailer < ApplicationMailer
def registrant_pending_updated(domain)
@domain = domain
return if Rails.env.production? ? false : !TEST_EMAILS.include?(@domain.registrant_email)
# turn on delivery on specific EPP request only, thus rake tasks does not deliver anything
return if @domain.deliver_emails != true
return if delivery_off?(@domain)
if @domain.registrant_verification_token.blank?
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"
@verification_url = "#{confirm_path}/#{@domain.id}?token=#{@domain.registrant_verification_token}"
return if whitelist_blocked?(@old_registrant.email)
mail(to: @old_registrant.email,
subject: "#{I18n.t(:domain_registrant_pending_updated_subject, name: @domain.name)} [#{@domain.name}]")
end
def registrant_updated(domain)
@domain = domain
return if Rails.env.production? ? false : !TEST_EMAILS.include?(@domain.registrant_email)
# turn on delivery on specific EPP request only, thus rake tasks does not deliver anything
return if @domain.deliver_emails != true
return if delivery_off?(@domain)
return if whitelist_blocked?(@domain.registrant_email)
mail(to: @domain.registrant_email,
subject: "#{I18n.t(:domain_registrant_updated, name: @domain.name)} [#{@domain.name}]")
end
def pending_deleted(domain)
@domain = domain
return if Rails.env.production? ? false : !TEST_EMAILS.include?(@domain.registrant_email)
# turn on delivery on specific EPP request only, thus rake tasks does not deliver anything
return if @domain.deliver_emails != true
return if delivery_off?(@domain)
if @domain.registrant_verification_token.blank?
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"
@verification_url = "#{confirm_path}/#{@domain.id}?token=#{@domain.registrant_verification_token}"
return if whitelist_blocked?(@old_registrant.email)
mail(to: @old_registrant.email,
subject: "#{I18n.t(:domain_pending_deleted_subject, name: @domain.name)} [#{@domain.name}]")
end

View file

@ -1,6 +1,6 @@
class InvoiceMailer < ApplicationMailer
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
attachments[invoice.pdf_name] = pdf

View file

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

View file

@ -141,7 +141,7 @@ class Certificate < ActiveRecord::Base
end
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("
mkdir -p #{ENV['crl_dir']}/crl-id-temp
@ -169,11 +169,11 @@ class Certificate < ActiveRecord::Base
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
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("
mkdir -p #{ENV['crl_dir']}/crl-temp
@ -192,13 +192,13 @@ class Certificate < ActiveRecord::Base
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
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")
STDOUT << "#{Time.zone.now.utc} - Apache reloaded\n"
STDOUT << "#{Time.zone.now.utc} - Apache reloaded\n" unless Rails.env.test?
end
def parse_md_from_string(crt)

View file

@ -5,10 +5,12 @@ class Contact < ActiveRecord::Base
belongs_to :registrar
has_many :domain_contacts
has_many :domains, through: :domain_contacts
has_many :statuses, class_name: 'ContactStatus', dependent: :destroy
has_many :legal_documents, as: :documentable
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
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 :code,
uniqueness: { message: :epp_id_taken },
format: { with: /\A[\w\-\:]*\Z/i },
length: { maximum: 100 }
format: { with: /\A[\w\-\:]*\Z/i, message: :invalid },
length: { maximum: 100, message: :too_long_contact_code }
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 :prefix_code
@ -37,10 +45,10 @@ class Contact < ActiveRecord::Base
ContactMailer.email_updated(self).deliver_now
end
after_save :manage_statuses
before_save :manage_statuses
def manage_statuses
ContactStatus.manage(statuses, self)
statuses.reload
manage_linked
manage_ok
end
scope :current_registrars, ->(id) { where(registrar_id: id) }
@ -58,6 +66,79 @@ class Contact < ActiveRecord::Base
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
def search_by_query(query)
res = search(code_cont: query).result
@ -83,6 +164,20 @@ class Contact < ActiveRecord::Base
def privs
where("ident_type = '#{PRIV}'")
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
def roid
@ -104,6 +199,12 @@ class Contact < ActiveRecord::Base
end
end
def uniq_statuses?
return true unless statuses.detect { |s| statuses.count(s) > 1 }
errors.add(:statuses, :not_uniq)
false
end
def bic?
ident_type == BIC
end
@ -206,4 +307,78 @@ class Contact < ActiveRecord::Base
@desc
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

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
hash
end
end
def initialize(attributes = {})
super
self.country_code = 'EE' if country_code.blank?
self.ident_type = 'bic' if ident_type.blank?
self.ident_country_code = 'EE' if ident_country_code.blank?
def type_string(type_code)
return '' if type_code.blank?
t = SELECTION_TYPES.select { |tp| tp.second == type_code }
t.try(:first).try(:first)
end
end
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 :street, to: :registrar, prefix: true
after_initialize :init_default_values
def init_default_values
after_initialize do
self.pending_json = {} if pending_json.blank?
self.statuses = [] if statuses.nil?
self.status_notes = {} if status_notes.nil?
end
before_create :generate_auth_info
@ -77,7 +78,6 @@ class Domain < ActiveRecord::Base
end
after_save :update_whois_record
after_initialize -> { self.statuses = [] if statuses.nil? }
after_create :update_reserved_domains
def update_reserved_domains

View file

@ -4,6 +4,13 @@ class Epp::Contact < Contact
# disable STI, there is type column present
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
# support legacy search
def find_by_epp_code(code)
@ -125,7 +132,9 @@ class Epp::Contact < Contact
[:ident, :invalid],
[:ident, :invalid_EE_identity_format],
[:ident, :invalid_birthday_format],
[:ident, :invalid_country_code]
[:ident, :invalid_country_code],
[:code, :invalid],
[:code, :too_long_contact_code]
],
'2302' => [ # Object exists
[:code, :epp_id_taken]

View file

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

View file

@ -13,6 +13,35 @@
= f.label :iban
.col-md-8
= 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
.row
.col-md-8.text-right

View file

@ -1,5 +1,6 @@
- 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)

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
%dt= t(:ident)
%dd= ident_for(@contact)

View file

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

View file

@ -1,125 +1,126 @@
- children = HashWithIndifferentAccess.new(version.children)
- nameservers = children[:nameservers] || []
- tech_contacts = children[:tech_contacts] || []
- admin_contacts = children[:admin_contacts] || []
- registrant = children[:registrant] || []
- if version.present? && domain.present?
- children = HashWithIndifferentAccess.new(version.children)
- nameservers = children[:nameservers] || []
- tech_contacts = children[:tech_contacts] || []
- admin_contacts = children[:admin_contacts] || []
- registrant = children[:registrant] || []
%td
%p.nowrap
= l(domain.updated_at, format: :short)
= version.event
%p.text-right
= version.terminator
%td
%p.nowrap
= l(domain.updated_at, format: :short)
= version.event
%p.text-right
= version.terminator
%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|
%td
%p
= oc[:name]
= oc[:phone]
= oc[:email]
= "#{domain.period}#{domain.period_unit}"
= "#{l(domain.valid_from, format: :date)} - #{l(domain.valid_to, format: :date)}"
%p
= oc[:code]
= domain.status
%td
- admin_contacts.each do |ac|
%td
- 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
= ac[:name]
= ac[:phone]
= ac[:email]
%p
= ac[:code]
= domain.registrar.name
%td
- tech_contacts.each do |tc|
%p
= tc[:name]
= tc[:phone]
= tc[:email]
%p
= tc[:code]
-# %td
-# = version.children.inspect
%td
- nameservers.each do |ns|
%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|
-# %td{ class: changes.include?(:domain) ? 'edit-highlight' : 'no-highlight' }
-# - if children[:domain]
-# %p{:style => "font-size:x-small;"}
-# = ac[:name]
-# = ","
-# = ac[:phone]
-# = ","
-# = ac[:email]
-# = ","
-# = ac[:code]
-# = 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?(:tech_contacts) ? 'edit-highlight' : 'no-highlight' }
-# - if children[:tech_contacts]
-# - children[:tech_contacts].each do |tc|
-# %td{ class: changes.include?(:registrant) ? 'edit-highlight' : 'no-highlight' }
-# - if children[:registrant]
-# %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' }
-# - if children[:nameservers]
-# - children[:nameservers].each do |ns|
-# %p{:style => "font-size:x-small;"}
-# = ns[:hostname]
-# = ","
-# = ns[:ipv4] || ns[:ipv6]
-# %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;"}
-# = ac[:name]
-# = ","
-# = ac[:phone]
-# = ","
-# = ac[:email]
-# = ","
-# = ac[:code]
-# %td
-# %p{ :style => 'font-size:x-small;' }
-# = l(version.created_at, format: :short)
-# = whodunnit_with_protocol(version.whodunnit)
-# = version.event
-# %td{ class: changes.include?(:tech_contacts) ? 'edit-highlight' : 'no-highlight' }
-# - if children[:tech_contacts]
-# - children[:tech_contacts].each do |tc|
-# %p{:style => "font-size:x-small;"}
-# = 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
.col-md-8.text-right
= button_tag(t(:save), class: 'btn btn-primary')
:coffee
$ ->
$("#tabs a:first").tab "show"

View file

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

View file

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

View file

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

View file

@ -30,5 +30,7 @@
.col-md-3.control-label
= f.label :country_code, t(:country) + '*'
.col-md-7
= f.select :country_code,
SortedCountry.all_options(f.object.country_code)
- country_selected = f.object.persisted? ? f.object.country_code : 'EE'
= 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
= f.label :ident_country_code, t(:country) + '*'
.col-md-7
= f.select(:ident_country_code, SortedCountry.all_options(f.object.ident_country_code), {},
class: 'js-ident-country-code', required: true, disabled: @contact.persisted?)
- if @contact.persisted? && f.object.ident_country_code.present?
.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
.col-md-3.control-label
= f.label :ident_type, t(:type) + '*'
.col-md-7
= f.select(:ident_type, Depp::Contact::SELECTION_TYPES, { selected: f.object.ident_type },
class: 'js-ident-type', required: true, disabled: @contact.persisted?)
- if @contact.persisted? && f.object.ident_type.present?
.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
.col-md-3.control-label
= f.label :ident, t(:ident) + '*'
.col-md-7
= 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)
- if f.object.ident.present?
.disabled-value
= f.object.ident
- 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-heading.clearfix

View file

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

View file

@ -4,7 +4,7 @@ app_name: '.EE Registry'
zonefile_export_dir: 'export/zonefiles'
bank_statement_import_dir: 'import/bank_statements'
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.
# 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'
# 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'
# Contact epp will not accept org value by default
# and returns 2306 "Parameter value policy error"
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
# iptables_counter_enabled: 'true'
@ -72,7 +76,7 @@ sk_digi_doc_service_name: 'EIS test'
# Autotest config overwrites
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_path: '/var/lib/jenkins/workspace/registry/ca/crl/crl.pem'
ca_cert_path: '/var/lib/jenkins/workspace/registry/ca/certs/ca.crt.pem'

View file

@ -1,7 +1,9 @@
dir_mode: script
dir: ../../log
dir: ../../log/que
multiple: true
backtrace: true
monitor: true
ontop: false
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:
<<: *default
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)
# alpha branch, all interfaces unified
set :domain, 'registry-st'
set :domain, 'registry'
set :deploy_to, '$HOME/registry'
set :repository, 'https://github.com/domify/registry' # dev repo
set :branch, 'master'
@ -20,7 +20,7 @@ set :que_restart, true
# alpha branch, only use for heavy debugging
task :epp do
set :domain, 'registry-st'
set :domain, 'registry'
set :deploy_to, '$HOME/epp'
set :repository, 'https://github.com/domify/registry' # dev repo
set :branch, 'master'
@ -30,7 +30,7 @@ end
# alpha branch, only use for heavy debugging
task :registrar do
set :domain, 'registry-st'
set :domain, 'registry'
set :deploy_to, '$HOME/registrar'
set :repository, 'https://github.com/domify/registry' # dev repo
set :branch, 'master'
@ -40,7 +40,7 @@ end
# alpha branch, only use for heavy debugging
task :registrant do
set :domain, 'registry-st'
set :domain, 'registryt'
set :deploy_to, '$HOME/registrant'
set :repository, 'https://github.com/domify/registry' # dev repo
set :branch, 'master'
@ -138,7 +138,8 @@ set :shared_paths, [
'public/system',
'export/zonefiles',
'import/bank_statements',
'import/legal_documents'
'import/legal_documents',
'tmp/pids'
]
# Optional settings:
@ -180,6 +181,9 @@ task setup: :environment do
queue! %(mkdir -p "#{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")
deploy do
invoke :'git:clone'
@ -199,30 +203,22 @@ task deploy: :environment do
# instance of your project.
invoke :'git:clone'
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 :'bundle:install'
invoke :'rails:db_migrate'
to :launch do
invoke :restart
invoke :'deploy:cleanup'
queue! "QUE_WORKER_COUNT=1 #{rake} daemon:que:restart" if que_restart
invoke :que_restart if que_restart
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'
task load_commit_hash: :environment do
queue! %(
@ -236,6 +232,11 @@ task restart: :environment do
queue "mkdir -p #{deploy_to}/current/tmp; touch #{deploy_to}/current/tmp/restart.txt"
end
desc 'Restart que server'
task que_restart: :environment do
queue "/etc/init.d/que restart"
end
namespace :cron do
desc 'Setup cron tasks.'
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,
# corresponding to the log level numbers from 0 up to 5 respectively
config.log_level = :fatal
config.log_level = :info
# for finding database optimization
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_key_path
ca_key_password
webclient_ip
webclient_ips
legal_documents_dir
bank_statement_import_dir
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_iban, 'EE557700771000598731')
Setting.save_default(:registry_bank, 'LHV Pank')
Setting.save_default(:registry_bank_code, '689')
Setting.save_default(:registry_swift, 'LHVBEE22')
Setting.save_default(:registry_invoice_contact, 'Martti Õigus')
end

View file

@ -36,6 +36,7 @@ en:
attributes:
code:
blank: "Required parameter missing - code"
too_long_contact_code: "Contact code is too long, max 100 characters"
name:
blank: "Required parameter missing - name"
phone:
@ -51,6 +52,8 @@ en:
invalid_country_code: "Ident country code is not valid, should be in ISO_3166-1 alpha 2 format"
domains:
exist: 'Object association prohibits operation'
statuses:
not_uniq: 'not uniq'
epp_domain: &epp_domain_ar_attributes
attributes:
@ -256,7 +259,7 @@ en:
invalid_type: 'PostalInfo type is invalid'
unimplemented_command: 'Unimplemented command'
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'
value: 'Value'
@ -832,7 +835,7 @@ en:
unset_force_delete: 'Unset force delete'
domain_expiring: 'Domain expiring'
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_transaction: 'Create bank transaction'
create_new_invoice: 'Create new invoice'
@ -869,4 +872,8 @@ en:
reserved_pw: 'Reserved pw'
no_transfers_found: 'No transfers found'
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.'
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.
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
enable_extension "plpgsql"
@ -200,6 +200,7 @@ ActiveRecord::Schema.define(version: 20150713113436) do
t.string "state"
t.integer "legacy_id"
t.string "statuses", array: true
t.hstore "status_notes"
end
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"
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|
t.integer "domain_id"
t.string "key_tag"
@ -327,6 +322,7 @@ ActiveRecord::Schema.define(version: 20150713113436) do
t.datetime "force_delete_at"
t.string "statuses", array: true
t.boolean "reserved", default: false
t.hstore "status_notes"
end
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,
state character varying,
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;
--
-- 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:
--
@ -945,7 +937,8 @@ CREATE TABLE domains (
pending_json json,
force_delete_at timestamp without time zone,
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);
--
-- 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:
--
@ -4861,10 +4847,6 @@ INSERT INTO schema_migrations (version) VALUES ('20150522164020');
INSERT INTO schema_migrations (version) VALUES ('20150525075550');
INSERT INTO schema_migrations (version) VALUES ('20150601083516');
INSERT INTO schema_migrations (version) VALUES ('20150601083800');
INSERT INTO schema_migrations (version) VALUES ('20150603141054');
INSERT INTO schema_migrations (version) VALUES ('20150603141549');
@ -4873,12 +4855,8 @@ INSERT INTO schema_migrations (version) VALUES ('20150603211318');
INSERT INTO schema_migrations (version) VALUES ('20150603212659');
INSERT INTO schema_migrations (version) VALUES ('20150609093515');
INSERT INTO schema_migrations (version) VALUES ('20150609103333');
INSERT INTO schema_migrations (version) VALUES ('20150610111019');
INSERT INTO schema_migrations (version) VALUES ('20150610112238');
INSERT INTO schema_migrations (version) VALUES ('20150610144547');
@ -4887,8 +4865,6 @@ INSERT INTO schema_migrations (version) VALUES ('20150611124920');
INSERT INTO schema_migrations (version) VALUES ('20150612123111');
INSERT INTO schema_migrations (version) VALUES ('20150612125720');
INSERT INTO schema_migrations (version) VALUES ('20150701074344');
INSERT INTO schema_migrations (version) VALUES ('20150703084632');
@ -4897,8 +4873,6 @@ INSERT INTO schema_migrations (version) VALUES ('20150706091724');
INSERT INTO schema_migrations (version) VALUES ('20150707103241');
INSERT INTO schema_migrations (version) VALUES ('20150707103801');
INSERT INTO schema_migrations (version) VALUES ('20150707104937');
INSERT INTO schema_migrations (version) VALUES ('20150707154543');
@ -4907,3 +4881,5 @@ INSERT INTO schema_migrations (version) VALUES ('20150709092549');
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
cd registry
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
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
exit
# 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
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,

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:
webclient_ip: '54.154.91.240'
webclient_ips: '54.154.91.240'
Configure EPP port 700 virtual host:
@ -215,7 +215,7 @@ After deploy, in rails console:
Certificate.update_crl
Update cron:
Update cron (mina tool example, when installed correctly):
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
<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:name> 1 Full name of the contact
<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.
Must add up to 1 / 2 / 3 years.
Attribute: unit="y/m/d"
Default is 1 year.
<domain:registrant> 1 Contact reference to the registrant
Attribute:
"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:name> 1 Domain name. Can contain unicode characters.
<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"
Default value is 1 year.
<extension> 0-1
<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.

View file

@ -22,9 +22,15 @@ Installation at deployed server:
sudo /etc/init.d/que start # for manual start
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

View file

@ -11,38 +11,35 @@
set -u
set -e
#
# Change these to match your server:
#
# Make sure that all paths are correct.
#
### CHANGES
APP_HOME="/home/registry/registry"
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
RUBY_BUNDLE_PATH=/home/$QUE_USER/.rbenv/shims/bundle
QUE_INSTANCES=1 # or as many really needed based real load
RUBY_BUNDLE=/home/$QUE_USER/.rbenv/shims/bundle
QUE_INSTANCES=1 # or as many really needed based on real load info
### END OF CHANGES
cd $APP_ROOT || exit 1
case ${1-help} in
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)
echo "$1 que monitor and server"
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
echo '.'
cd $APP_ROOT && QUE_WORKER_COUNT=1 RAILS_ENV=$RAILS_ENV QUE_USER=$QUE_USER $RUBY_BUNDLE exec rake daemon:que:start
echo 'que instance started'
done
;;
stop)
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)
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>"

View file

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

View file

@ -12,3 +12,7 @@ namespace :assets do
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'
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
extension = {
ident: {
@ -189,6 +202,31 @@ describe 'EPP Contact', epp: true do
response[:result_code].should == '2005'
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
response = create_request({ id: { value: 'CID:FIRST0:abc:ABC:NEW:12345' } })
response[:msg].should == 'Command completed successfully'

View file

@ -435,6 +435,24 @@ describe 'EPP Domain', epp: true do
a.activity_type = AccountActivity::CREATE
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
old_balance = @registrar1.balance
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
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
xml = domain_create_xml({}, {
_anonymus: [
@ -2185,16 +2221,14 @@ describe 'EPP Domain', epp: true do
### RENEW ###
it 'renews a domain' do
Setting.days_to_renew_domain_before_expire = 0
old_balance = @registrar1.balance
old_activities = @registrar1.cash_account.account_activities.count
domain.valid_to = Time.zone.now.to_date + 10.days
domain.save
exp_date = domain.valid_to.to_date
exp_date = domain.valid_to
xml = @epp_xml.domain.renew(
name: { value: domain.name },
curExpDate: { value: exp_date.to_s },
curExpDate: { value: exp_date.to_date.to_s },
period: { value: '1', attrs: { unit: 'y' } }
)
@ -2204,9 +2238,16 @@ describe 'EPP Domain', epp: true do
ex_date = response[:parsed].css('renData exDate').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
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
@ -2214,6 +2255,93 @@ describe 'EPP Domain', epp: true do
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 '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
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[:result_code].should == '2501'
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
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[:msg].should == 'Authentication error; server closing connection (API user is not active)'
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
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[:result_code].should == '2306'
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
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-Disposition'].should == "attachment; filename=\"#{@invoice.pdf_name}\""
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

View file

@ -97,7 +97,13 @@ describe Contact do
it 'should not accept long code' do
@contact.code = 'verylongcode' * 100
@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
it 'should have no related domain descriptions' do
@ -154,17 +160,36 @@ describe Contact do
end
it 'should have ok status by default' do
@contact.statuses.size.should == 1
@contact.statuses.first.value.should == 'ok'
@contact.statuses.should == %w(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
it 'should have linked status when domain' do
@tech_domain_contact = Fabricate(:tech_domain_contact, contact_id: @contact.id)
@domain = Fabricate(:domain, tech_domain_contacts: [@tech_domain_contact])
contact = @domain.contacts.first
contact.save
contact = Fabricate(:contact)
tech_domain_contact = Fabricate(:tech_domain_contact, contact_id: contact.id)
contact.statuses.should == %w(ok)
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
it 'should not have linked status when no domain' do
@ -173,11 +198,11 @@ describe Contact do
contact = @domain.contacts.first
contact.save
contact.statuses.map(&:value).sort.should == %w(linked ok)
contact.statuses.sort.should == %w(linked ok)
contact.domains.first.destroy
contact.reload
contact.statuses.map(&:value).should == %w(ok)
contact.statuses.should == %w(ok)
end
it 'should have code' do
@ -193,6 +218,15 @@ describe Contact do
# contact.statuses.map(&:value).should == %w(ok linked)
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
before do
@domain = Fabricate(:domain)

View file

@ -2,7 +2,7 @@ require 'rails_helper'
describe Repp::AccountV1 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)])
@api_user = Fabricate(:api_user, registrar: @registrar1)
@ -11,7 +11,7 @@ describe Repp::AccountV1 do
body = JSON.parse(response.body)
body['error'].should == 'IP is not whitelisted'
ENV['webclient_ip'] = '127.0.0.1'
ENV['webclient_ips'] = '127.0.0.1'
end
context 'with valid registrar' do

View file

@ -77,5 +77,14 @@ describe Repp::DomainV1 do
# TODO: Log failed API requests too
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