Removed and updated additional files

This commit is contained in:
Sergei Tsõganov 2022-10-13 14:06:33 +03:00
parent 11c2af075a
commit 04b55068df
29 changed files with 154 additions and 1534 deletions

View file

@ -1,227 +0,0 @@
class Registrar
class DomainsController < DeppController
before_action :init_domain, except: :new
helper_method :contacts
helper_method :search_params
def index
authorize! :view, Depp::Domain
if search_params.to_h.delete_if { |_key, value| value.blank? }.length == 1 &&
search_params[:name_matches].present?
domain = Domain.find_by(name: search_params[:name_matches])
redirect_to info_registrar_domains_url(domain_name: domain.name) and return if domain
end
domains = if params[:statuses_contains]
current_domain_scope.where('domains.statuses @> ?::varchar[]',
"{#{params[:statuses_contains].join(',')}}")
else
current_domain_scope
end
domains = domains.where(contacts: { ident: params[:contacts_ident_eq] }) if params[:contacts_ident_eq]
normalize_search_parameters do
@q = domains.ransack(search_params.except(:contacts_ident_eq))
@domains = @q.result.page(params[:page])
# if we do not get any results, add wildcards to the name field and search again
if @domains.count == 0 && search_params[:name_matches] !~ /^%.+%$/
new_search_params = search_params.to_h.except(:contacts_ident_eq)
new_search_params[:name_matches] = "%#{new_search_params[:name_matches]}%"
@q = domains.ransack(new_search_params)
@domains = @q.result.page(params[:page])
end
end
respond_to do |format|
format.html
format.csv do
domain_presenters = []
@q.result.find_each do |domain|
domain_presenters << ::DomainPresenter.new(domain: domain, view: view_context)
end
raw_csv = Registrar::DomainListCsvPresenter.new(domains: domain_presenters,
view: view_context).to_s
filename = "Domains_#{l(Time.zone.now, format: :filename)}.csv"
send_data raw_csv, filename: filename, type: "#{Mime[:csv]}; charset=utf-8"
end
end
end
def current_domain_scope
current_registrar_user.registrar.domains.includes(:registrar, :registrant)
end
def info
authorize! :info, Depp::Domain
@data = @domain.info(params[:domain_name]) if params[:domain_name]
@pending_delete = domain_delete_pending(@data)
@client_holded = client_holded(@data)
if response_ok?
render 'info'
else
flash[:alert] = @data.css('msg').text
redirect_to registrar_domains_url and return
end
end
def check
authorize! :check, Depp::Domain
if params[:domain_name]
@data = @domain.check(params[:domain_name])
render 'check_index' and return unless response_ok?
else
render 'check_index'
end
end
def new
authorize! :create, Depp::Domain
@domain_params = Depp::Domain.default_params
@domain_params[:period] = Depp::Domain.default_period
end
# rubocop:disable Metrics/CognitiveComplexity
def create
authorize! :create, Depp::Domain
@domain_params = domain_params.to_h
@data = @domain.create(@domain_params)
if @data && response_ok?
redirect_to info_registrar_domains_url(domain_name: @domain_params[:name])
else
flash[:alert] = t('.email_error_message') unless @emails_check_result
render 'new'
end
end
def edit
authorize! :update, Depp::Domain
@data = @domain.info(params[:domain_name])
@domain_params = Depp::Domain.construct_params_from_server_data(@data)
@dispute = Dispute.active.find_by(domain_name: params[:domain_name])
end
def update
authorize! :update, Depp::Domain
@domain_params = params[:domain]
@data = @domain.update(@domain_params)
@dispute = Dispute.active.find_by(domain_name: @domain_params[:name])
if @data && response_ok?
redirect_to info_registrar_domains_url(domain_name: @domain_params[:name])
else
flash[:alert] = t('.email_error_message') unless @emails_check_result
params[:domain_name] = @domain_params[:name]
render 'new'
end
end
# rubocop:enable Metrics/CognitiveComplexity
def delete
authorize! :delete, Depp::Domain
end
def destroy
authorize! :delete, Depp::Domain
@data = @domain.delete(params[:domain])
@results = @data.css('result')
if response_ok?
flash[:notice] = t('.deleting_request')
redirect_to info_registrar_domains_url(domain_name: params[:domain][:name])
else
params[:domain_name] = params[:domain][:name]
render 'delete'
end
end
def renew
authorize! :renew, Depp::Domain
if params[:domain_name] && params[:cur_exp_date]
@data = @domain.renew(params)
render 'renew_index' and return unless response_ok?
else
params[:period] = Depp::Domain.default_period
render 'renew_index'
end
end
def search_contacts
authorize! :create, Depp::Domain
scope = current_registrar_user.registrar.contacts.limit(10)
if params[:query].present?
escaped_str = ActiveRecord::Base.connection.quote_string params[:query]
scope = scope.where("name ilike '%#{escaped_str}%' OR code ilike '%#{escaped_str}%' ")
end
render json: scope.pluck(:name, :code).map { |c| { display_key: "#{c.second} #{c.first}", value: c.second } }
end
def remove_hold
authorize! :remove_hold, Depp::Domain
return unless params[:domain_name]
@data = @domain.remove_hold(params)
flash[:alert] = @data.css('msg').text unless response_ok?
redirect_to info_registrar_domains_url(domain_name: params[:domain_name])
end
private
def init_domain
@domain = Depp::Domain.new(current_user: depp_current_user)
end
def client_holded(data)
data.css('status')&.map { |element| element.attribute('s').value }
&.any? { |status| status == DomainStatus::CLIENT_HOLD }
end
def domain_delete_pending(data)
data.css('status')&.map { |element| element.attribute('s').value }
&.any? { |status| status.include?(DomainStatus::PENDING_DELETE) }
end
def contacts
current_registrar_user.registrar.contacts
end
def normalize_search_parameters
ca_cache = search_params[:valid_to_lteq]
begin
end_time = search_params[:valid_to_lteq].try(:to_date)
search_params[:valid_to_lteq] = end_time.try(:end_of_day)
rescue
logger.warn('Invalid date')
end
yield
search_params[:valid_to_lteq] = ca_cache
end
def search_params
params.fetch(:q, {}).permit(:name_matches,
:registrant_ident_eq,
:contacts_ident_eq,
:nameservers_hostname_eq,
:valid_to_gteq,
:valid_to_lteq,
:s)
end
def domain_params
params.require(:domain).permit(:name, :period, :registrant, :registrant_helper, :reserved_pw,
:verified, :legal_document, contacts_attributes: {},
nameservers_attributes: {},
dnskeys_attributes: {})
end
end
end

View file

@ -43,7 +43,7 @@ module Repp
def validate_renew_period
@epp_errors ||= ActiveModel::Errors.new(self)
periods = Depp::Domain::PERIODS.map { |p| p[1] }
periods = Domain::PERIODS.map { |p| p[1] }
return if periods.include? bulk_renew_params[:renew_period]
@epp_errors.add(:epp_errors, msg: 'Invalid renew period', code: '2005')

View file

@ -1,6 +0,0 @@
module Registrar::ApplicationHelper
def env_style
return '' if unstable_env.nil?
"background-image: url(#{image_path("registrar/bg-#{unstable_env}.png")});"
end
end

View file

@ -32,9 +32,7 @@ class Ability
def epp # Registrar/api_user dynamic role
if @user.registrar.api_ip_white?(@ip)
can :manage, Depp::Contact
can :manage, :xml_console
can :manage, Depp::Domain
end
can :manage, Account
@ -122,7 +120,6 @@ class Ability
customer_service
can :manage, :registrant_domains
can :manage, :registrant_whois
can :manage, Depp::Domain
can :manage, Domain
end

View file

@ -1,318 +0,0 @@
module Depp
class Contact
include ActiveModel::Model
attr_accessor :id, :name, :email, :phone, :org_name,
:ident, :ident_type, :ident_country_code,
:street, :city, :zip, :state, :country_code,
:password, :legal_document, :statuses, :code,
:email_history
DISABLED = 'Disabled'
DISCLOSURE_TYPES = [DISABLED, '1', '0']
TYPES = %w( org priv birthday )
SELECTION_TYPES = [
['Business code', 'org'],
['Personal identification code', 'priv'],
['Birthday', 'birthday']
]
validates :phone, e164: true, phone: true
class << self
attr_reader :epp_xml, :user
def new_from_params(params)
new(
id: params[:code],
code: params[:code],
email: params[:email],
phone: params[:phone],
ident: params[:ident],
ident_type: params[:ident_type],
ident_country_code: params[:ident_country_code],
# postalInfo
name: params[:name],
org_name: params[:org_name],
# address
street: params[:street],
city: params[:city],
zip: params[:zip],
state: params[:state],
country_code: params[:country_code]
)
end
def find_by_id(id)
data = info_xml(id)
res = data.css('epp response resData infData')
ext = data.css('epp response extension')
new(
id: res.css('id').text,
code: res.css('id').text,
email: res.css('email').text,
phone: res.css('voice').text,
ident: ext.css('ident').text,
ident_type: ext.css('ident').first.try(:attributes).try(:[], 'type').try(:value),
ident_country_code: ext.css('ident').first.try(:attributes).try(:[], 'cc').try(:value),
# postalInfo
name: res.css('postalInfo name').text,
org_name: res.css('postalInfo org').text,
# address
street: res.css('postalInfo addr street').text,
city: res.css('postalInfo addr city').text,
zip: res.css('postalInfo addr pc').text,
state: res.css('postalInfo addr sp').text,
country_code: res.css('postalInfo addr cc').text,
# authInfo
password: res.css('authInfo pw').text,
# statuses
statuses: data.css('status').map { |s| [s['s'], s.text] }
)
end
def user=(user)
@user = user
@epp_xml = EppXml::Contact.new(cl_trid_prefix: user.tag, schema_prefix: 'contact-ee',
schema_version: '1.1')
end
def info_xml(id, password = nil)
xml = epp_xml.info(
id: { value: id },
authInfo: { pw: { value: password } }
)
user.request(xml)
end
def construct_check_hash_from_data(data)
res = data.css('epp response resData chkData cd')
@contacts = []
res.each do |_r|
id = res.css('id').try(:text)
reason = res.css('reason').present? ? res.css('reason').text : I18n.t(:available)
@contacts << { id: id, reason: reason }
end
@contacts
end
def contact_id_from_xml(data)
id = data.css('epp response resData creData id').text
id.blank? ? nil : id
end
def construct_create_disclosure_xml(cph, flag)
xml = { disclose: {} }
cph.each do |k, v|
xml[:disclose][k] = {}
xml[:disclose][k][:value] = v
end
xml[:disclose][:attrs] = {}
xml[:disclose][:attrs][:flag] = flag
xml.with_indifferent_access
end
# cpd = contact_params[:disclose]
def extract_disclosure_hash(cpd)
return {} unless cpd
cpd.delete_if { |k, v| v if v != '1' && k == 'flag' }
end
def extract_info_disclosure(data)
hash = {}
data.css('disclose').each do |d|
flag = d.attributes['flag'].value
next unless flag
hash[flag] = {}
d.children.each do |c|
hash[flag][c.name] = flag if %w( name email fax voice addr org_name ).include?(c.name)
end
end
hash
end
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
return false unless valid?
hash = {
id: { value: code },
postalInfo: {
name: { value: name },
org: { value: org_name },
},
voice: { value: phone },
email: { value: email }
}
if ::Contact.address_processing?
hash[:postalInfo][:addr] = {
street: { value: street },
city: { value: city },
sp: { value: state },
pc: { value: zip },
cc: { value: country_code },
}
end
hash[:id] = nil if code.blank?
create_xml = Depp::Contact.epp_xml.create(hash, extension_xml(:create))
data = Depp::Contact.user.request(create_xml)
self.id = data.css('id').text
handle_errors(data)
end
# rubocop:disable Metrics/MethodLength
def update_attributes(params)
return false unless valid?
self.ident_country_code = params[:ident_country_code]
self.ident_type = params[:ident_type]
self.ident = params[:ident]
self.name = params[:name]
self.email = params[:email]
self.phone = params[:phone]
self.org_name = params[:org_name]
if ::Contact.address_processing?
self.street = params[:street]
self.city = params[:city]
self.zip = params[:zip]
self.state = params[:state]
self.country_code = params[:country_code]
end
attributes = {
id: { value: id },
chg: {
postalInfo: {
name: { value: name },
org: { value: org_name },
},
voice: { value: phone },
email: { value: email },
authInfo: {
pw: { value: password }
}
}
}
if ::Contact.address_processing?
attributes[:chg][:postalInfo][:addr] = {
street: { value: street },
city: { value: city },
sp: { value: state },
pc: { value: zip },
cc: { value: country_code }
}
end
update_xml = Depp::Contact.epp_xml.update(attributes, extension_xml(:update))
data = Depp::Contact.user.request(update_xml)
handle_errors(data)
end
# rubocop:enable Metrics/MethodLength
def delete
delete_xml = Contact.epp_xml.delete(
{
id: { value: id },
authInfo: { pw: { value: password } }
},
extension_xml(:delete)
)
data = Depp::Contact.user.request(delete_xml)
handle_errors(data)
end
def extension_xml(action)
xml = { _anonymus: [] }
case action
when :create
ident = ident_xml[:_anonymus].try(:first)
when :update
# detect if any ident has changed, nb! ident and self.ident is not always same
unless ident == self.ident && ident == ident_type && ident_country_code == self.ident_country_code
ident = ident_xml[:_anonymus].try(:first)
end
end
legal = legal_document_xml[:_anonymus].try(:first)
xml[:_anonymus] << ident if ident.present?
xml[:_anonymus] << legal if legal.present?
xml
end
def ident_xml
{
_anonymus: [
ident: { value: ident, attrs: { type: ident_type, cc: ident_country_code } }
]
}
end
def legal_document_xml
return {} if legal_document.blank?
type = legal_document.original_filename.split('.').last.downcase
{
_anonymus: [
legalDocument: { value: Base64.encode64(legal_document.read), attrs: { type: type } }
]
}
end
def check(id)
xml = epp_xml.check(id: { value: id })
current_user.request(xml)
end
def country_name
Country.new(country_code) || 'No access'
end
def org?
ident_type == 'org'
end
def priv?
ident_type == 'priv'
end
def persisted?
id.present?
end
def handle_errors(data)
data.css('result').each do |x|
success_codes = %(1000, 1300, 1301)
next if success_codes.include?(x['code'])
message = "#{x.css('msg').text} #{x.css('value').text}"
attr = message.split('[').last.strip.sub(']', '') if message.include?('[')
attr = :base if attr.nil?
attr = 'phone' if attr == 'voice'
attr = 'zip' if attr == 'pc'
errors.add(attr, message)
end
errors.blank?
end
end
end

View file

@ -1,26 +0,0 @@
module Depp
class Dnskey
FLAGS = [
['0 - not for DNSSEC validation', 0],
['256 - ZSK', 256],
['257 - KSK', 257]
]
ALGORITHMS = [
['3 - DSA/SHA-1', 3],
['5 - RSA/SHA-1', 5],
['6 - DSA-NSEC3-SHA1', 6],
['7 - RSASHA1-NSEC3-SHA1', 7],
['8 - RSA/SHA-256', 8],
['10 - RSA/SHA-512', 10],
['13 - ECDSA Curve P-256 with SHA-256', 13],
['14 - ECDSA Curve P-384 with SHA-384', 14],
['15 - Ed25519', 15],
['16 - Ed448', 16],
].freeze
PROTOCOLS = [3]
DS_DIGEST_TYPES = [1, 2]
end
end

View file

@ -1,351 +0,0 @@
module Depp
class Domain
include ActiveModel::Conversion
include RemoveHold
extend ActiveModel::Naming
attr_accessor :name, :current_user, :epp_xml
STATUSES = %w[
clientDeleteProhibited
clientHold
clientRenewProhibited
clientTransferProhibited
clientUpdateProhibited
].freeze
PERIODS = [
['3 months', '3m'],
['6 months', '6m'],
['9 months', '9m'],
['1 year', '1y'],
['2 years', '2y'],
['3 years', '3y'],
['4 years', '4y'],
['5 years', '5y'],
['6 years', '6y'],
['7 years', '7y'],
['8 years', '8y'],
['9 years', '9y'],
['10 years', '10y'],
].freeze
def initialize(args = {})
self.current_user = args[:current_user]
self.epp_xml = EppXml::Domain.new(
cl_trid_prefix: current_user.tag,
schema_prefix: 'domain-ee',
schema_version: '1.1'
)
end
def info(domain_name)
xml = epp_xml.info(name: { value: domain_name })
current_user.request(xml)
end
def check(domain_name)
xml = epp_xml.check(
_anonymus: [
name: { value: domain_name }
]
)
current_user.request(xml)
end
def create(domain_params)
dns_hash = {}
keys = Domain.create_dnskeys_hash(domain_params)
dns_hash[:_anonymus] = keys if keys.any?
period = domain_params[:period].to_i.to_s
period_unit = domain_params[:period][-1].to_s
xml = if domain_params[:nameservers_attributes]
.select { |_key, value| value['hostname'].present? }.any?
epp_xml.create({
name: { value: domain_params[:name] },
period: { value: period, attrs: { unit: period_unit } },
ns: Domain.create_nameservers_hash(domain_params),
registrant: { value: domain_params[:registrant] },
_anonymus: Domain.create_contacts_hash(domain_params)
}, dns_hash, Domain.construct_custom_params_hash(domain_params))
else
epp_xml.create({
name: { value: domain_params[:name] },
period: { value: period, attrs: { unit: period_unit } },
registrant: { value: domain_params[:registrant] },
_anonymus: Domain.create_contacts_hash(domain_params)
}, dns_hash, Domain.construct_custom_params_hash(domain_params))
end
current_user.request(xml)
end
def update(domain_params)
data = current_user.request(epp_xml.info(name: { value: domain_params[:name] }))
old_domain_params = Depp::Domain.construct_params_from_server_data(data)
xml = epp_xml.update(
Depp::Domain.construct_edit_hash(domain_params, old_domain_params),
Depp::Domain.construct_ext_edit_hash(domain_params, old_domain_params),
Depp::Domain.construct_custom_params_hash(domain_params)
)
current_user.request(xml)
end
def delete(domain_params)
xml = epp_xml.delete({
name: { value: domain_params[:name] },
},
Depp::Domain.construct_custom_params_hash(domain_params),
(domain_params[:verified].present? && 'yes'))
current_user.request(xml)
end
def renew(params)
period = params[:period].to_i.to_s
period_unit = params[:period][-1].to_s
current_user.request(epp_xml.renew(name: { value: params[:domain_name] },
curExpDate: { value: params[:cur_exp_date] },
period: { value: period, attrs: { unit: period_unit } }))
end
def transfer(params)
op = params[:request] ? 'request' : nil
op = params[:query] ? 'query' : op
op = params[:approve] ? 'approve' : op
op = params[:reject] ? 'reject' : op
current_user.request(epp_xml.transfer({
name: { value: params[:domain_name] },
authInfo: { pw: { value: params[:transfer_code] } }
}, op, Domain.construct_custom_params_hash(params)))
end
def confirm_transfer(domain_params)
data = current_user.request(epp_xml.info(name: { value: domain_params[:name] }))
pw = data.css('pw').text
xml = epp_xml.transfer({
name: { value: domain_params[:name] },
authInfo: { pw: { value: pw } }
}, 'approve')
current_user.request(xml)
end
class << self
def default_period
'1y'
end
def default_params
ret = {}
ret[:contacts_attributes] ||= {}
ENV['default_admin_contacts_count'].to_i.times do |i|
ret[:contacts_attributes][i] = { code: '', type: 'admin' }
end
ret[:nameservers_attributes] ||= {}
ENV['default_nameservers_count'].to_i.times do |i|
ret[:nameservers_attributes][i] = {}
end
ret[:dnskeys_attributes] ||= { 0 => {} }
ret[:statuses_attributes] ||= { 0 => {} }
ret.with_indifferent_access
end
def construct_params_from_server_data(data)
ret = default_params
ret[:name] = data.css('name').text
ret[:registrant] = data.css('registrant').text
data.css('contact').each_with_index do |x, i|
ret[:contacts_attributes][i] = { code: x.text, type: x['type'] }
end
data.css('hostAttr').each_with_index do |x, i|
ret[:nameservers_attributes][i] = {
hostname: x.css('hostName').text,
ipv4: Array(x.css('hostAddr[ip="v4"]')).map(&:text).join(','),
ipv6: Array(x.css('hostAddr[ip="v6"]')).map(&:text).join(',')
}
end
data.css('keyData').each_with_index do |x, i|
ret[:dnskeys_attributes][i] = {
flags: x.css('flags').text,
protocol: x.css('protocol').text,
alg: x.css('alg').text,
public_key: x.css('pubKey').text,
ds_key_tag: x.css('keyTag').first.try(:text),
ds_alg: x.css('alg').first.try(:text),
ds_digest_type: x.css('digestType').first.try(:text),
ds_digest: x.css('digest').first.try(:text)
}
end
data.css('status').each_with_index do |x, i|
next unless STATUSES.include?(x['s'])
ret[:statuses_attributes][i] = {
code: x['s'],
description: x.text
}
end
ret
end
def construct_custom_params_hash(domain_params)
custom_params = { _anonymus: [] }
if domain_params[:legal_document].present?
type = domain_params[:legal_document].original_filename.split('.').last.downcase
custom_params[:_anonymus] << {
legalDocument: { value: Base64.encode64(domain_params[:legal_document].read), attrs: { type: type } }
}
end
if domain_params[:reserved_pw].present?
custom_params[:_anonymus] << { reserved: { pw: { value: domain_params[:reserved_pw] } } }
end
custom_params
end
def construct_edit_hash(domain_params, old_domain_params)
contacts = array_difference(create_contacts_hash(domain_params), create_contacts_hash(old_domain_params))
add_anon = contacts
contacts = array_difference(create_contacts_hash(old_domain_params), create_contacts_hash(domain_params))
rem_anon = contacts
add_arr = []
add_ns = create_nameservers_hash(domain_params) - create_nameservers_hash(old_domain_params)
add_arr << { ns: add_ns } if add_ns.any?
add_arr << { _anonymus: add_anon } if add_anon.any?
rem_arr = []
rem_ns = create_nameservers_hash(old_domain_params) - create_nameservers_hash(domain_params)
rem_arr << { ns: rem_ns } if rem_ns.any?
rem_arr << { _anonymus: rem_anon } if rem_anon.any?
if domain_params[:registrant] != old_domain_params[:registrant]
chg = [{ registrant: { value: domain_params[:registrant] } }] unless domain_params[:verified].present?
if domain_params[:verified]
chg = [{ registrant: { value: domain_params[:registrant], attrs: { verified: 'yes' } } }]
end
end
add_arr = nil if add_arr.none?
rem_arr = nil if rem_arr.none?
{
name: { value: domain_params[:name] },
add: add_arr,
rem: rem_arr,
chg: chg
}
end
def construct_ext_edit_hash(domain_params, old_domain_params)
rem_keys = create_dnskeys_hash(old_domain_params) - create_dnskeys_hash(domain_params)
add_keys = create_dnskeys_hash(domain_params) - create_dnskeys_hash(old_domain_params)
hash = {}
hash[:rem] = rem_keys if rem_keys.any?
hash[:add] = add_keys if add_keys.any?
hash
end
def create_nameservers_hash(domain_params)
ret = []
domain_params[:nameservers_attributes].each do |_k, v|
next if v['hostname'].blank?
host_attr = []
host_attr << { hostName: { value: v['hostname'] } }
if v['ipv4'].present?
v['ipv4'].to_s.split(',').each do |ip|
host_attr << { hostAddr: { value: ip, attrs: { ip: 'v4' } } }
end
end
if v['ipv6'].present?
v['ipv6'].to_s.split(',').each do |ip|
host_attr << { hostAddr: { value: ip, attrs: { ip: 'v6' } } }
end
end
ret << { hostAttr: host_attr }
end
ret
end
def create_contacts_hash(domain_params)
ret = []
domain_params[:contacts_attributes].each do |_k, v|
next if v['code'].blank?
ret << {
contact: { value: v['code'], attrs: { type: v['type'] } }
}
end
ret
end
def create_dnskeys_hash(domain_params)
ret = []
domain_params[:dnskeys_attributes].each do |_k, v|
if v['ds_key_tag'].blank?
kd = create_key_data_hash(v)
if kd
ret << {
keyData: kd
}
end
else
ret << {
dsData: [
keyTag: { value: v['ds_key_tag'] },
alg: { value: v['ds_alg'] },
digestType: { value: v['ds_digest_type'] },
digest: { value: v['ds_digest'] },
keyData: create_key_data_hash(v)
]
}
end
end
ret
end
def create_key_data_hash(key_data_params)
return nil if key_data_params['public_key'].blank?
{
flags: { value: key_data_params['flags'] },
protocol: { value: key_data_params['protocol'] },
alg: { value: key_data_params['alg'] },
pubKey: { value: key_data_params['public_key'] }
}
end
def array_difference(x, y)
ret = x.dup
y.each do |element|
index = ret.index(element)
ret.delete_at(index) if index
end
ret
end
end
end
end

View file

@ -1,66 +0,0 @@
module Depp
class User
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :tag, :password, :pki
validates :tag, :password, presence: true
validate :validate_existance_in_server
def initialize(args = {})
args.each { |k, v| send("#{k}=", v) }
end
def server
client_cert = File.read(ENV['cert_path'])
client_key = File.read(ENV['key_path'])
port = ENV['epp_port'] || '700'
@server_cache ||= Epp::Server.new({
server: ENV['epp_hostname'],
tag: tag,
password: password,
port: port,
cert: OpenSSL::X509::Certificate.new(client_cert),
key: OpenSSL::PKey::RSA.new(client_key)
})
end
def request(xml)
Nokogiri::XML(server.request(xml)).remove_namespaces!
rescue EppErrorResponse => e
Nokogiri::XML(e.response_xml.to_s).remove_namespaces!
end
private
def validate_existance_in_server
return if errors.any?
res = server.open_connection
unless Nokogiri::XML(res).css('greeting')
errors.add(:base, :failed_to_open_connection_to_epp_server)
server.close_connection # just in case
return
end
ex = EppXml::Session.new(cl_trid_prefix: tag)
xml = ex.login(clID: { value: tag }, pw: { value: password })
res = server.send_request(xml)
if Nokogiri::XML(res).css('result').first['code'] != '1000'
errors.add(:base, Nokogiri::XML(res).css('result').text)
end
server.close_connection
rescue OpenSSL::SSL::SSLError => e
Rails.logger.error "INVALID CERT: #{e}"
Rails.logger.error "INVALID CERT DEBUG INFO: epp_hostname: #{ENV['epp_hostname']}," \
"port: #{ENV['epp_port']}, cert_path: #{ENV['cert_path']}, key_path: #{ENV['key_path']}"
errors.add(:base, :invalid_cert)
end
end
end

View file

@ -25,10 +25,10 @@ class Dnskey < ApplicationRecord
}
# IANA numbers, single authority list
ALGORITHMS = Depp::Dnskey::ALGORITHMS.map {|pair| pair[1].to_s}.freeze
PROTOCOLS = %w(3)
FLAGS = %w(0 256 257) # 256 = ZSK, 257 = KSK
DS_DIGEST_TYPE = [1,2]
ALGORITHMS = %w[3 5 6 7 8 10 13 14 15 16].freeze
PROTOCOLS = %w[3].freeze
FLAGS = %w[0 256 257].freeze # 256 = ZSK, 257 = KSK
DS_DIGEST_TYPE = [1, 2].freeze
RESOLVERS = ENV['dnssec_resolver_ips'].to_s.strip.split(', ').freeze
self.ignored_columns = %w[legacy_domain_id]

View file

@ -13,6 +13,22 @@ class Domain < ApplicationRecord
include Domain::Disputable
include Domain::BulkUpdatable
PERIODS = [
['3 months', '3m'],
['6 months', '6m'],
['9 months', '9m'],
['1 year', '1y'],
['2 years', '2y'],
['3 years', '3y'],
['4 years', '4y'],
['5 years', '5y'],
['6 years', '6y'],
['7 years', '7y'],
['8 years', '8y'],
['9 years', '9y'],
['10 years', '10y'],
].freeze
attr_accessor :roles,
:legal_document_id,
:is_admin,

View file

@ -1,45 +0,0 @@
class Registrar::DomainListCsvPresenter
def initialize(domains:, view:)
@domains = domains
@view = view
end
def to_s
table = CSV::Table.new([header])
domains.each do |domain|
table << domain_to_row(domain: domain)
end
table.to_s
end
private
def header
columns = %w[
domain_name
transfer_code
registrant_name
registrant_code
expire_time
]
columns.map! { |column| view.t("registrar.domains.index.csv.#{column}") }
CSV::Row.new(columns, [], true)
end
def domain_to_row(domain:)
row = []
row[0] = domain.name
row[1] = domain.transfer_code
row[2] = domain.registrant.name
row[3] = domain.registrant.code
row[4] = domain.expire_date
CSV::Row.new([], row)
end
attr_reader :domains, :view
end

View file

@ -1,7 +1,7 @@
- content_for :actions do
= link_to(t(:add), new_admin_invoice_path, class: 'btn btn-primary')
= render 'shared/title', name: t(:invoices)
= render 'search_form'
= render 'admin/invoices/partials/search_form'
.row
.col-md-12

View file

@ -0,0 +1,23 @@
%h4= t(:buyer)
%hr
%dl.dl-horizontal
%dt= t(:name)
%dd= @invoice.buyer_name
%dt= t(:reg_no)
%dd= @invoice.buyer_reg_no
%dt= t(:address)
%dd= @invoice.buyer_address
%dt= t(:country)
%dd= @invoice.buyer_country
%dt= t(:phone)
%dd= @invoice.buyer_phone
%dt= t(:url)
%dd= @invoice.buyer_url
%dt= t(:email)
%dd= @invoice.buyer_email

View file

@ -36,4 +36,4 @@
%dd=@invoice.description
%dt= Invoice.human_attribute_name :reference_no
%dd= @invoice.reference_no
%dd= @invoice.reference_no

View file

@ -0,0 +1,32 @@
%h4= t(:items)
%hr
.table-responsive
%table.table.table-hover.table-condensed
%thead
%tr
%th{class: 'col-xs-4'}= t(:description)
%th{class: 'col-xs-2'}= t(:unit)
%th{class: 'col-xs-2'}= InvoiceItem.human_attribute_name :quantity
%th{class: 'col-xs-2'}= t(:price)
%th{class: 'col-xs-2'}= t(:total)
%tbody
- @invoice.each do |invoice_item|
%tr
%td= invoice_item.description
%td= invoice_item.unit
%td= invoice_item.quantity
%td= currency(invoice_item.price)
%td= currency(invoice_item.item_sum_without_vat)
%tfoot
%tr
%th{colspan: 3}
%th= Invoice.human_attribute_name :subtotal
%td= number_to_currency @invoice.subtotal
%tr
%th.no-border{colspan: 3}
%th= "VAT #{number_to_percentage(@invoice.vat_rate, precision: 1)}"
%td= number_to_currency @invoice.vat_amount
%tr
%th.no-border{colspan: 3}
%th= t(:total)
%td= number_to_currency @invoice.total

View file

@ -0,0 +1,19 @@
%h4= "Payment Orders"
%hr
.table-responsive
%table.table.table-hover.table-condensed
%thead
%tr
%th{class: 'col-xs-1'}= "#"
%th{class: 'col-xs-1'}= "Channel"
%th{class: 'col-xs-2'}= "Status"
%th{class: 'col-xs-3'}= "Initiated"
%th{class: 'col-xs-4'}= "Notes"
%tbody
- @invoice.payment_orders.each do |payment_order|
%tr
%td= payment_order.id
%td= payment_order.channel
%td= payment_order.status
%td= payment_order.created_at
%td= payment_order.notes

View file

@ -69,10 +69,10 @@
<span class="glyphicon glyphicon-search"></span>
&nbsp;
</button>
<%= link_to t('.download_btn'), admin_invoices_path(format: :csv, params: params.permit!),
"data-toggle" => "tooltip", "data-placement" => "bottom", "title" => t('.download_btn'),
<%= link_to t('admin.invoices.search_form.download_btn'), admin_invoices_path(format: :csv, params: params.permit!),
"data-toggle" => "tooltip", "data-placement" => "bottom", "title" => t('admin.invoices.search_form.download_btn'),
class: 'btn btn-default' %>
<%= link_to t('.reset_btn'), admin_invoices_path, class: 'btn btn-default' %>
<%= link_to t('admin.invoices.search_form.reset_btn'), admin_invoices_path, class: 'btn btn-default' %>
</div>
</div>
<% end %>

View file

@ -0,0 +1,38 @@
%h4= t(:seller)
%hr
%dl.dl-horizontal
%dt= t(:name)
%dd= @invoice.seller_name
%dt= Registrar.human_attribute_name :reg_no
%dd= @invoice.seller_reg_no
%dt= t(:iban)
%dd= @invoice.seller_iban
%dt= t(:bank)
%dd= @invoice.seller_bank
%dt= t(:swift)
%dd= @invoice.seller_swift
%dt= Registrar.human_attribute_name :vat_no
%dd= @invoice.seller_vat_no
%dt= t(:address)
%dd= @invoice.seller_address
%dt= t(:country)
%dd= @invoice.seller_country
%dt= t(:phone)
%dd= @invoice.seller_phone
%dt= t(:url)
%dd= @invoice.seller_url
%dt= t(:email)
%dd= @invoice.seller_email
%dt= t(:issuer)
%dd= @invoice.seller_contact_name

View file

@ -20,200 +20,14 @@
= render 'shared/full_errors', object: @invoice
.row
.col-md-6
%h4= t(:details)
%hr
%dl.dl-horizontal
%dt= t(:issue_date)
%dd= l @invoice.issue_date
- if @invoice.cancelled?
%dt= Invoice.human_attribute_name :cancelled_at
%dd= l @invoice.cancelled_at
%dt= t(:due_date)
- if @invoice.cancelled?
%dd.text-grey= t(:cancelled)
- else
%dd= l @invoice.due_date
%dt= Invoice.human_attribute_name :receipt_date
- if @invoice.paid?
%dd= l @invoice.receipt_date
- elsif @invoice.cancelled?
%dd.text-grey= t(:cancelled)
- else
%dd{class: 'text-danger'}= t(:unpaid)
%dt= t(:payment_term)
%dd Prepayment
%dt= t(:invoice_number)
%dd= @invoice.number
- if @invoice.description.present?
%dt= t(:description)
%dd=@invoice.description
%dt= Invoice.human_attribute_name :reference_no
%dd= @invoice.reference_no
.col-md-6= render 'admin/invoices/partials/details'
.row
.col-md-6
%h4= t(:seller)
%hr
%dl.dl-horizontal
%dt= t(:name)
%dd= @invoice.seller_name
%dt= Registrar.human_attribute_name :reg_no
%dd= @invoice.seller_reg_no
%dt= t(:iban)
%dd= @invoice.seller_iban
%dt= t(:bank)
%dd= @invoice.seller_bank
%dt= t(:swift)
%dd= @invoice.seller_swift
%dt= Registrar.human_attribute_name :vat_no
%dd= @invoice.seller_vat_no
%dt= t(:address)
%dd= @invoice.seller_address
%dt= t(:country)
%dd= @invoice.seller_country
%dt= t(:phone)
%dd= @invoice.seller_phone
%dt= t(:url)
%dd= @invoice.seller_url
%dt= t(:email)
%dd= @invoice.seller_email
%dt= t(:issuer)
%dd= @invoice.seller_contact_name
.col-md-6
%h4= t(:buyer)
%hr
%dl.dl-horizontal
%dt= t(:name)
%dd= @invoice.buyer_name
%dt= t(:reg_no)
%dd= @invoice.buyer_reg_no
%dt= t(:address)
%dd= @invoice.buyer_address
%dt= t(:country)
%dd= @invoice.buyer_country
%dt= t(:phone)
%dd= @invoice.buyer_phone
%dt= t(:url)
%dd= @invoice.buyer_url
%dt= t(:email)
%dd= @invoice.buyer_email
.col-md-6= render 'admin/invoices/partials/seller'
.col-md-6= render 'admin/invoices/partials/buyer'
.row
- if @invoice.monthly_invoice
.col-md-12
%h4= t(:items)
%hr
.table-responsive
%table.table.table-hover.table-condensed
%thead
%tr
%th{class: 'col-xs-1'}= t(:code)
%th{class: 'col-xs-1'}= InvoiceItem.human_attribute_name :quantity
%th{class: 'col-xs-1'}= t(:unit)
%th{class: 'col-xs-5'}= t(:description)
%th{class: 'col-xs-2'}= t(:price)
%th{class: 'col-xs-2'}= t(:total)
%tbody
- @invoice.each do |invoice_item|
%tr
%td= invoice_item.product_id
%td= invoice_item.quantity
%td= invoice_item.unit
%td= invoice_item.description
- if invoice_item.price && invoice_item.quantity
%td= currency(invoice_item.price)
%td= "#{currency((invoice_item.price * invoice_item.quantity).round(3))} #{@invoice.currency}"
- else
%td= ''
%td= ''
%tfoot
%tr
%th{colspan: 4}
%th= Invoice.human_attribute_name :subtotal
%td= number_to_currency(0)
%tr
%th.no-border{colspan: 4}
%th= "VAT #{number_to_percentage(@invoice.vat_rate, precision: 1)}"
%td= number_to_currency(0)
%tr
%th.no-border{colspan: 4}
%th= t(:total)
%td= number_to_currency(0)
- if @invoice.monthly_invoice
.col-md-12= render 'admin/invoices/partials/monthly_invoice_items'
- else
.col-md-12
%h4= t(:items)
%hr
.table-responsive
%table.table.table-hover.table-condensed
%thead
%tr
%th{class: 'col-xs-4'}= t(:description)
%th{class: 'col-xs-2'}= t(:unit)
%th{class: 'col-xs-2'}= InvoiceItem.human_attribute_name :quantity
%th{class: 'col-xs-2'}= t(:price)
%th{class: 'col-xs-2'}= t(:total)
%tbody
- @invoice.each do |invoice_item|
%tr
%td= invoice_item.description
%td= invoice_item.unit
%td= invoice_item.quantity
%td= currency(invoice_item.price)
%td= currency(invoice_item.item_sum_without_vat)
%tfoot
%tr
%th{colspan: 3}
%th= Invoice.human_attribute_name :subtotal
%td= number_to_currency @invoice.subtotal
%tr
%th.no-border{colspan: 3}
%th= "VAT #{number_to_percentage(@invoice.vat_rate, precision: 1)}"
%td= number_to_currency @invoice.vat_amount
%tr
%th.no-border{colspan: 3}
%th= t(:total)
%td= number_to_currency @invoice.total
.col-md-12= render 'admin/invoices/partials/items'
.row
.col-md-12
%h4= "Payment Orders"
%hr
.table-responsive
%table.table.table-hover.table-condensed
%thead
%tr
%th{class: 'col-xs-1'}= "#"
%th{class: 'col-xs-1'}= "Channel"
%th{class: 'col-xs-2'}= "Status"
%th{class: 'col-xs-3'}= "Initiated"
%th{class: 'col-xs-4'}= "Notes"
%tbody
- @invoice.payment_orders.each do |payment_order|
%tr
%td= payment_order.id
%td= payment_order.channel
%td= payment_order.status
%td= payment_order.created_at
%td= payment_order.notes
.col-md-12= render 'admin/invoices/partials/payment_orders'

View file

@ -1,64 +0,0 @@
<!DOCTYPE html>
<html lang="<%= I18n.locale.to_s %>">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<% if content_for? :head_title %>
<%= yield :head_title %>
<% else %>
<title>
<%= t(:registrar_head_title) %>
</title>
<% end %>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'registrar-manifest', media: 'all' %>
<%= favicon_link_tag 'favicon.ico' %>
</head>
<body class="<%= body_css_class %>">
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button aria-expanded="false" class="navbar-toggle collapsed" data-target="#navbar" data-toggle="collapse" type="button">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<%= link_to can?(:show, :poll) ? registrar_root_path : registrar_account_path,
class: 'navbar-brand' do %>
<%= t(:registrar_head_title) %>
<% if unstable_env.present? %>
<div class="text-center">
<small style="color: #0074B3;">
<%= unstable_env %>
</small>
</div>
<% end %>
<% end %>
</div>
<%= render 'navbar' %>
</div>
</nav>
<div class="container">
<%= render 'flash_messages' %>
<% if depp_controller? %>
<%= render 'registrar/shared/epp_results' %>
<% end %>
<%= yield %>
</div>
<footer class="footer">
<div class="container">
<div class="row">
<div class="col-md-6">
<%= image_tag 'eis-logo-et.png' %>
</div>
<div class="col-md-6 text-right">
Version
<%= current_commit_link %>
</div>
</div>
</div>
</footer>
<%= javascript_include_tag 'registrar-manifest', async: true %>
</body>
</html>

View file

@ -1,23 +0,0 @@
- content_for :actions do
= link_to(t('.download_btn'), download_registrar_invoice_path(@invoice), class: 'btn btn-default')
= link_to(t('.deliver_btn'), new_registrar_invoice_delivery_path(@invoice), class: 'btn btn-default')
- if @invoice.cancellable?
= link_to(t(:cancel), cancel_registrar_invoice_path(@invoice), method: :patch, class: 'btn btn-warning')
= link_to(t(:back), registrar_invoices_path, class: 'btn btn-default')
= render 'shared/title', name: @invoice.to_s
= render 'shared/full_errors', object: @invoice
.row
.col-md-6= render 'registrar/invoices/partials/details'
.row
.col-md-6= render 'registrar/invoices/partials/seller'
.col-md-6= render 'registrar/invoices/partials/buyer'
.row
- if @invoice.monthly_invoice
.col-md-12= render 'registrar/invoices/partials/monthly_invoice_items'
- else
.col-md-12= render 'registrar/invoices/partials/items'
- if @invoice.payable?
.row.semifooter
.col-md-6-offset-6.text-right= render 'registrar/invoices/partials/banklinks', locals: { payment_channels: PaymentOrder::CUSTOMER_PAYMENT_METHODS }

View file

@ -61,16 +61,6 @@ contact_org_enabled: 'false'
# System default for legal document types is: pdf,asice,sce,asics,scs,adoc,edoc,bdoc,ddoc,zip,rar,gz,tar,7z,odt,doc,docx
# legal_document_types: "pdf,asice,sce,asics,scs,adoc,edoc,bdoc,ddoc,zip,rar,gz,tar,7z,odt,doc,docx"
#
# REGISTRAR configuration (DEPP)
#
show_ds_data_fields: 'false'
default_nameservers_count: '2'
default_admin_contacts_count: '1'
epp_port: '700'
cert_path: '/home/registry/registry/shared/ca/certs/webclient.cert.pem'
key_path: '/home/registry/registry/shared/ca/private/webclient.key.pem'
epp_hostname: 'registry.gitlab.eu'
repp_url: 'http://epp:3000/repp/v1/'
# Estonian Company Register

View file

@ -380,29 +380,6 @@ en:
client_side_status_editing_error: 'Parameter value policy error. Client-side object status management not supported'
parameter_value_syntax_error: 'Parameter value syntax error:'
# DEPP
activemodel:
errors:
models:
'depp/contact':
attributes:
phone:
invalid: "Phone number must be in +XXX.YYYYYYY format"
too_long: "Phone number is too long"
'depp/user':
attributes:
base:
failed_to_open_connection_to_epp_server: 'Failed to open connection to EPP server!'
authorization_error: 'Authorization error'
invalid_cert: 'Invalid certificate'
not_active: 'User is not active'
webserver_missing_user_name_directive: 'Webserver configuration error: Apache or nginx is missing user name directive.'
webserver_user_name_directive_should_be_required: 'Webserver configuration error: Apache or nginx should require name directive.'
tag:
blank: "Username can't be blank"
password:
blank: "Password can't be blank"
username: 'Username'
register: 'Register'
domain_info: 'Domain info'

View file

@ -24,13 +24,11 @@ class ReppV1DomainsDnssecTest < ActionDispatch::IntegrationTest
{ flags: '256',
alg: '14',
protocol: '3',
public_key: 'dGVzdA=='
}
]
public_key: 'dGVzdA==' },
],
}
post "/repp/v1/domains/#{@domain.name}/dnssec", params: payload, headers: @auth_headers
json = JSON.parse(response.body, symbolize_names: true)
get "/repp/v1/domains/#{@domain.name}/dnssec", headers: @auth_headers
json = JSON.parse(response.body, symbolize_names: true)
@ -45,9 +43,8 @@ class ReppV1DomainsDnssecTest < ActionDispatch::IntegrationTest
{ flags: '256',
alg: '14',
protocol: '3',
public_key: 'dGVzdA=='
}
]
public_key: 'dGVzdA==' },
],
}
post "/repp/v1/domains/#{@domain.name}/dnssec", params: payload, headers: @auth_headers
@ -67,7 +64,7 @@ class ReppV1DomainsDnssecTest < ActionDispatch::IntegrationTest
end
def test_creates_dnssec_key_with_every_algo
algos = Depp::Dnskey::ALGORITHMS.map {|pair| pair[1].to_s}
algos = Dnskey::ALGORITHMS
algos_to_check = %w[15 16]
assert (algos & algos_to_check) == algos_to_check
@ -79,9 +76,8 @@ class ReppV1DomainsDnssecTest < ActionDispatch::IntegrationTest
{ flags: '256',
alg: alg,
protocol: '3',
public_key: 'dGVzdA=='
}
]
public_key: 'dGVzdA==' },
],
}
post "/repp/v1/domains/#{@domain.name}/dnssec", params: payload, headers: @auth_headers
@ -105,13 +101,11 @@ class ReppV1DomainsDnssecTest < ActionDispatch::IntegrationTest
{ flags: '256',
alg: '14',
protocol: '3',
public_key: 'dGVzdA=='
}
]
public_key: 'dGVzdA==' },
],
}
post "/repp/v1/domains/#{@domain.name}/dnssec", params: payload, headers: @auth_headers
json = JSON.parse(response.body, symbolize_names: true)
assert @domain.dnskeys.any?

View file

@ -1,14 +0,0 @@
require 'test_helper'
require 'helpers/phone_format_helper_test'
class DeppContactTest < ActiveSupport::TestCase
include PhoneFormatHelperTest
setup do
@depp_contact = Depp::Contact.new
end
def test_validates_phone_format
assert_phone_format(@depp_contact)
end
end

View file

@ -1,44 +0,0 @@
require 'application_system_test_case'
class BalanceTopUpTest < ApplicationSystemTestCase
setup do
sign_in users(:api_bestnames)
@original_registry_vat_rate = Setting.registry_vat_prc
eis_response = OpenStruct.new(body: "{\"payment_link\":\"http://link.test\"}")
Spy.on_instance_method(EisBilling::AddDeposits, :send_invoice).and_return(eis_response)
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
end
teardown do
Setting.registry_vat_prc = @original_registry_vat_rate
end
def test_creates_new_invoice
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response")
.to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice")
.to_return(status: 200, body: "", headers: {})
Setting.registry_vat_prc = 0.1
visit registrar_invoices_url
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '25.5'
assert_difference 'Invoice.count' do
click_link_or_button 'Add'
end
invoice = Invoice.last
assert_equal BigDecimal(10), invoice.vat_rate
assert_equal BigDecimal('28.05'), invoice.total
assert_text 'Please pay the following invoice'
end
end

View file

@ -1,96 +0,0 @@
require 'application_system_test_case'
class NewInvoiceTest < ApplicationSystemTestCase
def setup
super
@user = users(:api_bestnames)
sign_in @user
eis_response = OpenStruct.new(body: "{\"payment_link\":\"http://link.test\"}")
Spy.on_instance_method(EisBilling::AddDeposits, :send_invoice).and_return(eis_response)
end
def test_show_balance
visit registrar_invoices_path
assert_text "Your current account balance is 100,00 EUR"
end
def test_create_new_invoice_with_positive_amount
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
visit registrar_invoices_path
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '200.00'
fill_in 'Description', with: 'My first invoice'
assert_difference 'Invoice.count', 1 do
click_link_or_button 'Add'
end
assert_text 'Please pay the following invoice'
assert_text "Invoice no. #{invoice_n + 3}"
assert_text 'Subtotal 200,00 €'
assert_text 'Pay invoice'
end
def test_create_new_invoice_with_comma_in_number
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
visit registrar_invoices_path
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '200,00'
fill_in 'Description', with: 'My first invoice'
assert_difference 'Invoice.count', 1 do
click_link_or_button 'Add'
end
assert_text 'Please pay the following invoice'
assert_text "Invoice no. #{invoice_n + 3}"
assert_text 'Subtotal 200,00 €'
assert_text 'Pay invoice'
end
def test_create_new_invoice_fails_when_amount_is_0
visit registrar_invoices_path
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '0.00'
fill_in 'Description', with: 'My first invoice'
assert_no_difference 'Invoice.count' do
click_link_or_button 'Add'
end
assert_text 'Amount is too small. Minimum deposit is 0.01 EUR'
end
def test_create_new_invoice_fails_when_amount_is_negative
visit registrar_invoices_path
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '-120.00'
fill_in 'Description', with: 'My first invoice'
assert_no_difference 'Invoice.count' do
click_link_or_button 'Add'
end
assert_text 'Amount is too small. Minimum deposit is 0.01 EUR'
end
end