diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb
index 89ccd9ac6..cc49b3b61 100644
--- a/app/controllers/admin/settings_controller.rb
+++ b/app/controllers/admin/settings_controller.rb
@@ -59,6 +59,7 @@ class Admin::SettingsController < AdminController
:transfer_wait_time,
:invoice_number_min,
:invoice_number_max,
+ :days_to_keep_business_registry_cache,
:days_to_keep_invoices_active,
:days_to_keep_overdue_invoices_active,
:days_to_renew_domain_before_expire,
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 5d051377d..ac26e61a3 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -32,7 +32,7 @@ class ApplicationController < ActionController::Base
if registrar_request?
registrar_root_url
elsif registrant_request?
- registrant_root_url
+ registrant_login_url
elsif admin_request?
admin_root_url
end
diff --git a/app/controllers/registrant/contacts_controller.rb b/app/controllers/registrant/contacts_controller.rb
new file mode 100644
index 000000000..d3a0ddff8
--- /dev/null
+++ b/app/controllers/registrant/contacts_controller.rb
@@ -0,0 +1,8 @@
+class Registrant::ContactsController < RegistrantController
+
+ def show
+ @contact = Contact.find(params[:id])
+ authorize! :read, @contact
+ @contact.valid?
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/registrant/domains_controller.rb b/app/controllers/registrant/domains_controller.rb
index 4bba945a8..bf7ce37bb 100644
--- a/app/controllers/registrant/domains_controller.rb
+++ b/app/controllers/registrant/domains_controller.rb
@@ -1,5 +1,64 @@
class Registrant::DomainsController < RegistrantController
+
def index
- authorize! :view, :registrant_domains
+ authorize! :view, :registrant_domains
+ params[:q] ||= {}
+ normalize_search_parameters do
+ @q = domains.search(params[:q])
+ @domains = @q.result.page(params[:page])
end
-end
+ @domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i > 0
+ end
+
+ def show
+ @domain = Domain.find(params[:id])
+ if !(domains.include?(@domain) || @domain.valid?)
+ redirect_to registrant_domains_path
+ end
+ authorize! :read, @domain
+ end
+
+ def set_domain
+ @domain = Domain.find(params[:id])
+ end
+
+ def download_list
+ authorize! :view, :registrant_domains
+ params[:q] ||= {}
+ normalize_search_parameters do
+ @q = domains.search(params[:q])
+ @domains = @q
+ end
+
+ respond_to do |format|
+ format.csv { render text: @domains.result.to_csv }
+ format.pdf do
+ pdf = @domains.result.pdf(render_to_string('registrant/domains/download_list', layout: false))
+ send_data pdf, filename: 'domains.pdf'
+ end
+ end
+ end
+
+ def domains
+ ident_cc, ident = @current_user.registrant_ident.split '-'
+ begin
+ BusinessRegistryCache.fetch_associated_domains ident, ident_cc
+ rescue Soap::Arireg::NotAvailableError => error
+ flash[:notice] = I18n.t(error.json[:message])
+ Rails.logger.fatal("[EXCEPTION] #{error.to_s}")
+ current_user.domains
+ end
+ end
+
+ def normalize_search_parameters
+ ca_cache = params[:q][:valid_to_lteq]
+ begin
+ end_time = params[:q][:valid_to_lteq].try(:to_date)
+ params[:q][:valid_to_lteq] = end_time.try(:end_of_day)
+ rescue
+ logger.warn('Invalid date')
+ end
+ yield
+ params[:q][:valid_to_lteq] = ca_cache
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/registrant/registrants_controller.rb b/app/controllers/registrant/registrants_controller.rb
new file mode 100644
index 000000000..adc1e0b82
--- /dev/null
+++ b/app/controllers/registrant/registrants_controller.rb
@@ -0,0 +1,8 @@
+class Registrant::RegistrantsController < RegistrantController
+
+ def show
+ @contact = Registrant.find(params[:id])
+ authorize! :read, @contact
+ @contact.valid?
+ end
+end
diff --git a/app/controllers/registrant/registrars_controller.rb b/app/controllers/registrant/registrars_controller.rb
new file mode 100644
index 000000000..d0630b73a
--- /dev/null
+++ b/app/controllers/registrant/registrars_controller.rb
@@ -0,0 +1,7 @@
+class Registrant::RegistrarsController < RegistrantController
+
+ def show
+ @registrar = Registrar.find(params[:id])
+ authorize! :read, @registrar
+ end
+end
diff --git a/app/controllers/registrant/sessions_controller.rb b/app/controllers/registrant/sessions_controller.rb
index f0a292137..91589d510 100644
--- a/app/controllers/registrant/sessions_controller.rb
+++ b/app/controllers/registrant/sessions_controller.rb
@@ -6,15 +6,10 @@ class Registrant::SessionsController < Devise::SessionsController
# rubocop: disable Metrics/AbcSize
def id
- if Rails.env.development?
- sign_in(RegistrantUser.find_or_create_by_idc_data('test'), event: :authentication)
- return redirect_to registrant_root_url
- end
+ id_code, id_issuer = request.env['SSL_CLIENT_S_DN'], request.env['SSL_CLIENT_I_DN_O']
+ id_code, id_issuer = 'test', RegistrantUser::ACCEPTED_ISSUER if Rails.env.development?
- logger.error request.env['SSL_CLIENT_S_DN']
- logger.error request.env['SSL_CLIENT_S_DN'].encoding
- logger.error request.env['SSL_CLIENT_I_DN_O']
- @user = RegistrantUser.find_or_create_by_idc_data(request.env['SSL_CLIENT_S_DN'], request.env['SSL_CLIENT_I_DN_O'])
+ @user = RegistrantUser.find_or_create_by_idc_data(id_code, id_issuer)
if @user
sign_in(@user, event: :authentication)
redirect_to registrant_root_url
diff --git a/app/controllers/registrant/whois_controller.rb b/app/controllers/registrant/whois_controller.rb
index 71d29dd76..b44a0bb67 100644
--- a/app/controllers/registrant/whois_controller.rb
+++ b/app/controllers/registrant/whois_controller.rb
@@ -1,5 +1,9 @@
class Registrant::WhoisController < RegistrantController
def index
authorize! :view, :registrant_whois
+
+ if params[:domain_name].present?
+ @domain = WhoisRecord.find_by(name: params[:domain_name]);
+ end
end
end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index cf98cb704..61f1edb2e 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -16,7 +16,7 @@ class Ability
@user.roles.each { |role| send(role) } if @user.roles
when 'ApiUser'
@user.roles.each { |role| send(role) } if @user.roles
- when 'RegistrantUser'
+ when 'RegistrantUser'
static_registrant
end
@@ -117,9 +117,11 @@ class Ability
end
def static_registrant
+ customer_service
can :manage, :registrant_domains
can :manage, :registrant_whois
can :manage, Depp::Domain
+ can :manage, Domain
end
def user
diff --git a/app/models/business_registry_cache.rb b/app/models/business_registry_cache.rb
new file mode 100644
index 000000000..5ca1e002c
--- /dev/null
+++ b/app/models/business_registry_cache.rb
@@ -0,0 +1,74 @@
+
+=begin
+The portal for registrants has to offer an overview of the domains the user is related to directly or through an organisation.
+Personal relation is defined by matching the personal identification code associated with a domain and the one acquired on
+authentication using electronic ID. Association through a business organisation requires a query to business registry.
+
+ * when user logs in the personal identification code is sent to business registry (using XML service)
+ * business registry returns the list of business registry codes the user is a board member of
+ * the list is cached for two days (configurable)
+ * during that time no new queries are made to business registry for that personal identification code
+ and the cached organisation code listing is used
+ * user sees the listing of domains that are associated with him/her directly or through registered organisation
+ * UI of the portal displays the list of organisation codes and names used to fetch additional domains for the user
+ (currently by clicking on a username in top right corner of the screen).
+ Also time and date of the query to the business registry is displayed with the list of organisations.
+ * if the query to the business registry fails for any reason the list of
+ domains associated directly with the user is still displayed with an error message indicating a problem
+ with receiving current list business entities. Outdated list of organisations cannot be used.
+=end
+
+class BusinessRegistryCache < ActiveRecord::Base
+
+ # 1. load domains by business
+ # 2. load domains by person
+ def associated_domains
+ domains = []
+
+ contact_ids = Contact.where(ident_type: 'org', ident: associated_businesses, ident_country_code: 'EE').pluck(:id)
+ contact_ids += Contact.where(ident_type: 'priv', ident: ident, ident_country_code: ident_country_code).pluck(:id)
+
+ unless contact_ids.blank?
+ domains = DomainContact.distinct.where(contact_id: contact_ids).pluck(:domain_id)
+ end
+
+ Domain.includes(:registrar, :registrant).where(id: domains)
+ end
+
+ class << self
+ def fetch_associated_domains(ident_code, ident_cc)
+ fetch_by_ident_and_cc(ident_code, ident_cc).associated_domains
+ end
+
+ def fetch_by_ident_and_cc(ident_code, ident_cc)
+ cache = BusinessRegistryCache.where(ident: ident_code, ident_country_code: ident_cc).first_or_initialize
+ msg_start = "[Ariregister] #{ident_cc}-#{ident_code}:"
+
+ # fetch new data if cache is expired
+ if cache.retrieved_on && cache.retrieved_on > (Time.zone.now - Setting.days_to_keep_business_registry_cache.days)
+ Rails.logger.info("#{msg_start} Info loaded from cache")
+ return cache
+ end
+
+ cache.attributes = business_registry.associated_businesses(ident_code, ident_cc)
+ Rails.logger.info("#{msg_start} Info loaded from server")
+
+ cache.save
+ cache
+ end
+
+ def business_registry
+ Soap::Arireg.new
+ end
+
+ def purge
+ STDOUT << "#{Time.zone.now.utc} - Starting Purge of old BusinessRegistry data from cache\n" unless Rails.env.test?
+ purged = 0
+ BusinessRegistryCache.where('retrieved_on < ?',
+ Time.zone.now < Setting.days_to_keep_business_registry_cache.days).each do |br|
+ br.destroy and purged += 1
+ end
+ STDOUT << "#{Time.zone.now.utc} - Finished purging #{purged} old BusinessRegistry cache items\n" unless Rails.env.test?
+ end
+ end
+end
diff --git a/app/models/domain.rb b/app/models/domain.rb
index 2063a2f8c..4bfa76b40 100644
--- a/app/models/domain.rb
+++ b/app/models/domain.rb
@@ -754,5 +754,19 @@ class Domain < ActiveRecord::Base
DomainMailer.send(action, DomainMailModel.new(self).send(action)).deliver
end
+
+ def self.to_csv
+ CSV.generate do |csv|
+ csv << column_names
+ all.each do |domain|
+ csv << domain.attributes.values_at(*column_names)
+ end
+ end
+ end
+
+ def self.pdf(html)
+ kit = PDFKit.new(html)
+ kit.to_pdf
+ end
end
# rubocop: enable Metrics/ClassLength
diff --git a/app/models/registrant_user.rb b/app/models/registrant_user.rb
index 9a69e8acb..413ff1202 100644
--- a/app/models/registrant_user.rb
+++ b/app/models/registrant_user.rb
@@ -1,4 +1,5 @@
class RegistrantUser < User
+ ACCEPTED_ISSUER = 'AS Sertifitseerimiskeskus'
attr_accessor :idc_data
def ability
@@ -6,6 +7,19 @@ class RegistrantUser < User
end
delegate :can?, :cannot?, to: :ability
+ def ident
+ registrant_ident.to_s.split("-").last
+ end
+
+ def domains
+ ident_cc, ident = registrant_ident.to_s.split '-'
+ Domain.includes(:registrar, :registrant).where(contacts: {
+ ident_type: 'priv',
+ ident: ident, #identity_code,
+ ident_country_code: ident_cc #country_code
+ })
+ end
+
def to_s
username
end
@@ -13,11 +27,9 @@ class RegistrantUser < User
class << self
def find_or_create_by_idc_data(idc_data, issuer_organization)
return false if idc_data.blank?
- return false if issuer_organization != 'AS Sertifitseerimiskeskus'
+ return false if issuer_organization != ACCEPTED_ISSUER
idc_data.force_encoding('UTF-8')
- logger.error(idc_data)
- logger.error(idc_data.encoding)
identity_code = idc_data.scan(/serialNumber=(\d+)/).flatten.first
country = idc_data.scan(/^\/C=(.{2})/).flatten.first
first_name = idc_data.scan(%r{/GN=(.+)/serialNumber}).flatten.first
diff --git a/app/models/soap/arireg.rb b/app/models/soap/arireg.rb
new file mode 100644
index 000000000..422a72dd9
--- /dev/null
+++ b/app/models/soap/arireg.rb
@@ -0,0 +1,219 @@
+# coding: utf-8
+require 'savon'
+=begin
+
+Estonian Business registry provides information about registered companies via xml (SOAP over HTTPS).
+
+Note:
+ The SSL endpoint certificate is self signed.
+
+Documentation:
+ http://www.rik.ee/et/e-ariregister/xml-teenus
+ Specifications are in Eng and Est
+ User contract required
+
+Testing:
+ https://demo-ariregxml.rik.ee:447/testariport/?wsdl
+ http://demo-ariregxml.rik.ee:81
+ https://demo-ariregxml.rik.ee:447
+
+Live service:
+ https://ariregxml.rik.ee/ariport/?wsdl
+ https://ariregxml.rik.ee/
+
+Implements Soap::Arireg # associated_businesses
+ 8. arireg.paringesindus_v4
+ Rights of representation of all persons related to the company (newer)
+ http://www2.rik.ee/schemas/xtee/arireg/live/paringesindus_v4.xsd
+ expects personal id code, to fetch list of registered business id codes
+ returning {ident: person, ident_country_code: ... associated_businesses: [...id_codes...]}
+
+=end
+
+# do some SSL set up?
+# ssl_version
+# ssl_verify_mode
+# ssl_cert_key_file
+# ssl_cert_key
+# ssl_cert_key_password
+# ssl_cert_file
+# ssl_cert
+# ssl_ca_cert_file
+# ssl_ca_cert
+
+module Soap
+
+ class Arireg
+
+ class NotAvailableError < StandardError
+ attr_accessor :json
+ def initialize(params)
+ params[:message] = "#{I18n.t(:business_registry_service_not_available)}" unless params.key? :message
+ @json = params
+
+ super(params)
+ end
+ end
+
+ class << self
+ attr_accessor :wsdl, :host, :username, :password
+ end
+
+ def initialize
+ if self.class.username.nil?
+ if Rails.application.secrets.key?(:arireg)
+ arireg = Rails.application.secrets[:arireg].with_indifferent_access
+ self.class.username = arireg[:username]
+ self.class.password = arireg[:password]
+ if self.class.wsdl.nil? # no override of config/environments/* ?
+ self.class.wsdl = arireg[:wsdl]
+ self.class.host = arireg[:host]
+ end
+ else
+ self.class.username = ENV['arireg_username']
+ self.class.password = ENV['arireg_password']
+ end
+ end
+ if self.class.wsdl.nil?
+ self.class.wsdl = ENV['arireg_wsdl']
+ self.class.host = ENV['arireg_host']
+ end
+
+ # note Savon has error if https w/non-standard port,
+ # use non-standard force to pre-set endpoint
+ @client = Savon.client(wsdl: self.class.wsdl,
+ host: self.class.host,
+ endpoint: "#{self.class.host}/cgi-bin/consumer_proxy")
+ @session = nil
+ end
+
+ # retrieve business id codes for business that a person has a legal role
+ def associated_businesses(ident, ident_cc = 'EST')
+ begin
+ msg = {
+ 'fyysilise_isiku_kood' => ident,
+ 'fyysilise_isiku_koodi_riik' => country_code_3(ident_cc)
+ }
+ Rails.logger.info "[Ariregister] Request sent with data: #{msg.inspect}"
+
+ response = @client.call :paringesindus_v4, message: body(msg)
+ content = extract response, :paringesindus_v4_response
+ Rails.logger.info "[Ariregister] Got response with data: #{content.inspect}"
+
+ if content.present? && content[:ettevotjad].key?(:item)
+ business_ident = items(content, :ettevotjad).map{|item| item[:ariregistri_kood]}
+ else
+ business_ident = []
+ end
+
+ {
+ ident: ident,
+ ident_country_code: ident_cc,
+ # ident_type: 'priv',
+ retrieved_on: Time.now,
+ associated_businesses: business_ident
+ }
+ rescue Savon::SOAPFault => fault
+ Rails.logger.error "[Ariregister] #{fault} Äriregister arireg #{self.class.username} at #{self.class.host }"
+ raise NotAvailableError.new(exception: fault)
+ rescue HTTPI::SSLError => ssl_error
+ Rails.logger.error "[Ariregister] #{ssl_error} at #{self.class.host}"
+ raise NotAvailableError.new(exception: ssl_error)
+ rescue SocketError => sock
+ Rails.logger.error "[Ariregister] #{sock}"
+ raise NotAvailableError.new(exception: sock)
+ end
+ end
+
+ def debug
+ @client.globals.log_level :debug
+ @client.globals.log true
+ @client.globals.pretty_print_xml true
+ @debug = true
+ @client
+ end
+
+ private
+
+ # add required elements to request
+ def body(args)
+ if @session.nil?
+ args['ariregister_kasutajanimi'] = self.class.username
+ args['ariregister_parool'] = self.class.password
+ else
+ args['ariregister_sessioon'] = @session
+ end
+ {keha: args}
+ end
+
+ # TLA --- three letter acronym required not two letter acronym, transform
+ def country_code_3(code)
+ if code.length == 2
+ code = CC2X3[code]
+ raise NotAvailableError.new(message: 'Unrecognized Country') if code.nil?
+ end
+ code
+ end
+
+ def extract(response, element)
+ # response envelope body has again header/body under element; header is user and password returned
+ response.hash[:envelope][:body][element][:keha]
+ end
+
+ def items(content, parent)
+ items = content[parent][:item]
+ items.is_a?(Array) ? items : [items]
+ end
+
+ CC2X3 = {"AF"=>"AFG", "AX"=>"ALA", "AL"=>"ALB", "DZ"=>"DZA", "AS"=>"ASM",
+ "AD"=>"AND", "AO"=>"AGO", "AI"=>"AIA", "AQ"=>"ATA", "AG"=>"ATG",
+ "AR"=>"ARG", "AM"=>"ARM", "AW"=>"ABW", "AU"=>"AUS", "AT"=>"AUT",
+ "AZ"=>"AZE", "BS"=>"BHS", "BH"=>"BHR", "BD"=>"BGD", "BB"=>"BRB",
+ "BY"=>"BLR", "BE"=>"BEL", "BZ"=>"BLZ", "BJ"=>"BEN", "BM"=>"BMU",
+ "BT"=>"BTN", "BO"=>"BOL", "BQ"=>"BES", "BA"=>"BIH", "BW"=>"BWA",
+ "BV"=>"BVT", "BR"=>"BRA", "IO"=>"IOT", "BN"=>"BRN", "BG"=>"BGR",
+ "BF"=>"BFA", "BI"=>"BDI", "CV"=>"CPV", "KH"=>"KHM", "CM"=>"CMR",
+ "CA"=>"CAN", "KY"=>"CYM", "CF"=>"CAF", "TD"=>"TCD", "CL"=>"CHL",
+ "CN"=>"CHN", "CX"=>"CXR", "CC"=>"CCK", "CO"=>"COL", "KM"=>"COM",
+ "CD"=>"COD", "CG"=>"COG", "CK"=>"COK", "CR"=>"CRI", "CI"=>"CIV",
+ "HR"=>"HRV", "CU"=>"CUB", "CW"=>"CUW", "CY"=>"CYP", "CZ"=>"CZE",
+ "DK"=>"DNK", "DJ"=>"DJI", "DM"=>"DMA", "DO"=>"DOM", "EC"=>"ECU",
+ "EG"=>"EGY", "SV"=>"SLV", "GQ"=>"GNQ", "ER"=>"ERI", "EE"=>"EST",
+ "ET"=>"ETH", "FK"=>"FLK", "FO"=>"FRO", "FJ"=>"FJI", "FI"=>"FIN",
+ "FR"=>"FRA", "GF"=>"GUF", "PF"=>"PYF", "TF"=>"ATF", "GA"=>"GAB",
+ "GM"=>"GMB", "GE"=>"GEO", "DE"=>"DEU", "GH"=>"GHA", "GI"=>"GIB",
+ "GR"=>"GRC", "GL"=>"GRL", "GD"=>"GRD", "GP"=>"GLP", "GU"=>"GUM",
+ "GT"=>"GTM", "GG"=>"GGY", "GN"=>"GIN", "GW"=>"GNB", "GY"=>"GUY",
+ "HT"=>"HTI", "HM"=>"HMD", "VA"=>"VAT", "HN"=>"HND", "HK"=>"HKG",
+ "HU"=>"HUN", "IS"=>"ISL", "IN"=>"IND", "ID"=>"IDN", "IR"=>"IRN",
+ "IQ"=>"IRQ", "IE"=>"IRL", "IM"=>"IMN", "IL"=>"ISR", "IT"=>"ITA",
+ "JM"=>"JAM", "JP"=>"JPN", "JE"=>"JEY", "JO"=>"JOR", "KZ"=>"KAZ",
+ "KE"=>"KEN", "KI"=>"KIR", "KP"=>"PRK", "KR"=>"KOR", "KW"=>"KWT",
+ "KG"=>"KGZ", "LA"=>"LAO", "LV"=>"LVA", "LB"=>"LBN", "LS"=>"LSO",
+ "LR"=>"LBR", "LY"=>"LBY", "LI"=>"LIE", "LT"=>"LTU", "LU"=>"LUX",
+ "MO"=>"MAC", "MK"=>"MKD", "MG"=>"MDG", "MW"=>"MWI", "MY"=>"MYS",
+ "MV"=>"MDV", "ML"=>"MLI", "MT"=>"MLT", "MH"=>"MHL", "MQ"=>"MTQ",
+ "MR"=>"MRT", "MU"=>"MUS", "YT"=>"MYT", "MX"=>"MEX", "FM"=>"FSM",
+ "MD"=>"MDA", "MC"=>"MCO", "MN"=>"MNG", "ME"=>"MNE", "MS"=>"MSR",
+ "MA"=>"MAR", "MZ"=>"MOZ", "MM"=>"MMR", "NA"=>"NAM", "NR"=>"NRU",
+ "NP"=>"NPL", "NL"=>"NLD", "NC"=>"NCL", "NZ"=>"NZL", "NI"=>"NIC",
+ "NE"=>"NER", "NG"=>"NGA", "NU"=>"NIU", "NF"=>"NFK", "MP"=>"MNP",
+ "NO"=>"NOR", "OM"=>"OMN", "PK"=>"PAK", "PW"=>"PLW", "PS"=>"PSE",
+ "PA"=>"PAN", "PG"=>"PNG", "PY"=>"PRY", "PE"=>"PER", "PH"=>"PHL",
+ "PN"=>"PCN", "PL"=>"POL", "PT"=>"PRT", "PR"=>"PRI", "QA"=>"QAT",
+ "RE"=>"REU", "RO"=>"ROU", "RU"=>"RUS", "RW"=>"RWA", "BL"=>"BLM",
+ "SH"=>"SHN", "KN"=>"KNA", "LC"=>"LCA", "MF"=>"MAF", "PM"=>"SPM",
+ "VC"=>"VCT", "WS"=>"WSM", "SM"=>"SMR", "ST"=>"STP", "SA"=>"SAU",
+ "SN"=>"SEN", "RS"=>"SRB", "SC"=>"SYC", "SL"=>"SLE", "SG"=>"SGP",
+ "SX"=>"SXM", "SK"=>"SVK", "SI"=>"SVN", "SB"=>"SLB", "SO"=>"SOM",
+ "ZA"=>"ZAF", "GS"=>"SGS", "SS"=>"SSD", "ES"=>"ESP", "LK"=>"LKA",
+ "SD"=>"SDN", "SR"=>"SUR", "SJ"=>"SJM", "SZ"=>"SWZ", "SE"=>"SWE",
+ "CH"=>"CHE", "SY"=>"SYR", "TW"=>"TWN", "TJ"=>"TJK", "TZ"=>"TZA",
+ "TH"=>"THA", "TL"=>"TLS", "TG"=>"TGO", "TK"=>"TKL", "TO"=>"TON",
+ "TT"=>"TTO", "TN"=>"TUN", "TR"=>"TUR", "TM"=>"TKM", "TC"=>"TCA",
+ "TV"=>"TUV", "UG"=>"UGA", "UA"=>"UKR", "AE"=>"ARE", "GB"=>"GBR",
+ "UM"=>"UMI", "US"=>"USA", "UY"=>"URY", "UZ"=>"UZB", "VU"=>"VUT",
+ "VE"=>"VEN", "VN"=>"VNM", "VG"=>"VGB", "VI"=>"VIR", "WF"=>"WLF",
+ "EH"=>"ESH", "YE"=>"YEM", "ZM"=>"ZMB", "ZW"=>"ZWE"}
+ end
+end
diff --git a/app/views/admin/settings/index.haml b/app/views/admin/settings/index.haml
index e09e48396..863d197d0 100644
--- a/app/views/admin/settings/index.haml
+++ b/app/views/admin/settings/index.haml
@@ -51,6 +51,7 @@
= render 'setting_row', var: :transfer_wait_time
= render 'setting_row', var: :ds_digest_type
= render 'setting_row', var: :client_side_status_editing_enabled
+ = render 'setting_row', var: :days_to_keep_business_registry_cache
= render 'setting_row', var: :api_ip_whitelist_enabled
= render 'setting_row', var: :registrar_ip_whitelist_enabled
= render 'setting_row', var: :request_confrimation_on_registrant_change_enabled
diff --git a/app/views/registrant/contacts/partials/_address.haml b/app/views/registrant/contacts/partials/_address.haml
new file mode 100644
index 000000000..9c0f548e3
--- /dev/null
+++ b/app/views/registrant/contacts/partials/_address.haml
@@ -0,0 +1,23 @@
+.panel.panel-default
+ .panel-heading
+ %h3.panel-title= t(:address)
+ .panel-body
+ %dl.dl-horizontal
+ - if @contact.org_name.present?
+ %dt= t(:org_name)
+ %dd= @contact.org_name
+
+ %dt= t(:street)
+ %dd= @contact.street.to_s.gsub("\n", '
').html_safe
+
+ %dt= t(:city)
+ %dd= @contact.city
+
+ %dt= t(:zip)
+ %dd= @contact.zip
+
+ %dt= t(:state)
+ %dd= @contact.state
+
+ %dt= t(:country)
+ %dd= @contact.country
diff --git a/app/views/registrant/contacts/partials/_domains.haml b/app/views/registrant/contacts/partials/_domains.haml
new file mode 100644
index 000000000..d0180532d
--- /dev/null
+++ b/app/views/registrant/contacts/partials/_domains.haml
@@ -0,0 +1,30 @@
+- domains = contact.all_domains(page: params[:domain_page], per: 20, params: params)
+#contacts.panel.panel-default
+ .panel-heading
+ .pull-left
+ = t(:domains)
+ .pull-right
+ = form_tag request.path, method: :get do
+ = select_tag :domain_filter, options_for_select(%w(Registrant AdminDomainContact TechDomainContact), selected: params[:domain_filter]),
+ include_blank: true, class: 'form-control2 selectize2'
+ %button.btn.btn-primary
+ %span.glyphicon.glyphicon-search
+ .clearfix
+
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-3'}=custom_sort_link t(:domain_name), :name
+ %th{class: 'col-xs-3'}=custom_sort_link t(:registrar), :registrar_name
+ %th{class: 'col-xs-3'}=custom_sort_link t(:valid_to), :valid_to
+ %th{class: 'col-xs-3'}= t(:roles)
+ %tbody
+ - domains.each do |x|
+ %tr
+ %td= link_to(x.name, [:registrant, x])
+ %td= link_to(x.registrar, [:registrant, x.registrar])
+ %td= l(x.valid_to, format: :short)
+ %td= x.roles.join(", ")
+
+= paginate domains, param_name: :domain_page
\ No newline at end of file
diff --git a/app/views/registrant/contacts/partials/_general.haml b/app/views/registrant/contacts/partials/_general.haml
new file mode 100644
index 000000000..36192cb2c
--- /dev/null
+++ b/app/views/registrant/contacts/partials/_general.haml
@@ -0,0 +1,45 @@
+.panel.panel-default
+ .panel-heading
+ %h3.panel-title= t(:general)
+ .panel-body
+ %dl.dl-horizontal
+ %dt= t(:id)
+ %dd= @contact.code
+
+ %dt= t(:password)
+ %dd
+ = text_field_tag :auth_info, @contact.auth_info, readonly: true, class: 'partially-hidden'
+
+ %br
+
+ %dt= t(:ident)
+ %dd= ident_for(@contact)
+
+ %dt= t(:email)
+ %dd= @contact.email
+
+ %dt= t(:phone)
+ %dd= @contact.phone
+
+ - if @contact.fax
+ %dt= t(:fax)
+ %dd= @contact.fax
+
+ %br
+
+ %dt= t(:created)
+ %dd
+ = l(@contact.created_at, format: :short)
+ by
+ = creator_link(@contact)
+
+ %dt= t(:updated)
+ %dd
+ = l(@contact.updated_at, format: :short)
+ by
+ = updator_link(@contact)
+
+ %dt= t(:registrar)
+ %dd
+ - if @contact.registrar.present?
+ = link_to(@contact.registrar, registrant_registrar_path(@contact.registrar))
diff --git a/app/views/registrant/contacts/partials/_search.haml b/app/views/registrant/contacts/partials/_search.haml
new file mode 100644
index 000000000..4a723bf6b
--- /dev/null
+++ b/app/views/registrant/contacts/partials/_search.haml
@@ -0,0 +1,6 @@
+= search_form_for [:registrant, @q] do |f|
+ = f.search_field :name_cont
+ = f.submit do
+ %span.glyphicon.glyphicon-search
+
+
diff --git a/app/views/registrant/contacts/partials/_statuses.haml b/app/views/registrant/contacts/partials/_statuses.haml
new file mode 100644
index 000000000..c39075754
--- /dev/null
+++ b/app/views/registrant/contacts/partials/_statuses.haml
@@ -0,0 +1,21 @@
+- panel_class = contact.errors.messages[:statuses] ? 'panel-danger' : 'panel-default'
+#contact_statuses.panel{class: panel_class}
+ .panel-heading.clearfix
+ = t(:statuses)
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-6'}= t(:status)
+ %th{class: 'col-xs-6'}= t(:notes)
+ %tbody
+ - contact.statuses.each do |status|
+ %tr
+ %td= status
+ %td= contact.status_notes[status]
+
+ - if contact.errors.messages[:statuses]
+ %tfoot
+ - @domain.errors.messages[:statuses].each do |s|
+ %tr
+ %td{colspan: 4}= s
diff --git a/app/views/registrant/contacts/show.haml b/app/views/registrant/contacts/show.haml
new file mode 100644
index 000000000..57915e9ff
--- /dev/null
+++ b/app/views/registrant/contacts/show.haml
@@ -0,0 +1,12 @@
+- content_for :actions do
+ = render 'shared/title', name: @contact.name
+
+.row
+ .col-md-6= render 'registrant/contacts/partials/general'
+ .col-md-6= render 'registrant/contacts/partials/address'
+.row
+ .col-md-12= render 'registrant/contacts/partials/statuses', contact: @contact
+.row
+ .col-md-12= render 'registrant/contacts/partials/domains', contact: @contact
+
+
diff --git a/app/views/registrant/domains/download_list.haml b/app/views/registrant/domains/download_list.haml
new file mode 100644
index 000000000..40212812c
--- /dev/null
+++ b/app/views/registrant/domains/download_list.haml
@@ -0,0 +1,28 @@
+!!!
+%html
+ %head
+ %meta{:content => "text/html; charset=utf-8", "http-equiv" => "Content-Type"}
+ %title Contacts
+ %body
+ .col-md-12
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-2'}
+ =t(:name)
+ %th{class: 'col-xs-2'}
+ =t(:registrant)
+ %th{class: 'col-xs-2'}
+ =t(:valid_to)
+ %th{class: 'col-xs-2'}
+ =t(:registrar)
+ %tbody
+ - @domains.result.each do |x|
+ %tr
+ %td= x.name
+ %td= x.registrant
+ %td= l(x.valid_to, format: :short)
+ %td= x.registrar
+ .row
+ .col-md-6
diff --git a/app/views/registrant/domains/index.haml b/app/views/registrant/domains/index.haml
index 8b71cefca..776b7878d 100644
--- a/app/views/registrant/domains/index.haml
+++ b/app/views/registrant/domains/index.haml
@@ -1,5 +1,52 @@
= render 'shared/title', name: t(:domains)
+.row
+ .col-md-12
+ = search_form_for [:registrant, @q], html: { style: 'margin-bottom: 0;', class: 'js-form', autocomplete: 'off' } do |f|
+ .row
+ .col-md-3
+ .form-group
+ = f.label :name
+ = f.search_field :name_matches, value: params[:q][:name_matches], class: 'form-control', placeholder: t(:name)
+ .col-md-3
+ .form-group
+ = f.label t(:registrant_ident)
+ = f.search_field :registrant_ident_eq, class: 'form-control', placeholder: t(:registrant_ident)
+ .row
+ .col-md-3
+ .form-group
+ = f.label t(:valid_to_from)
+ = f.search_field :valid_to_gteq, value: params[:q][:valid_to_gteq], class: 'form-control datepicker', placeholder: t(:valid_to_from)
+ .col-md-3
+ .form-group
+ = f.label t(:valid_to_until)
+ = f.search_field :valid_to_lteq, value: params[:q][:valid_to_lteq], class: 'form-control datepicker', placeholder: t(:valid_to_until)
+ .col-md-3
+ .form-group
+ = label_tag t(:results_per_page)
+ = text_field_tag :results_per_page, params[:results_per_page], class: 'form-control', placeholder: t(:results_per_page)
+ .col-md-3{style: 'padding-top: 25px;'}
+ %button.btn.btn-primary
+
+ %span.glyphicon.glyphicon-search
+
+ %button.btn.btn-default.js-reset-form
+ = t(:clear_fields)
+ .row
+ .col-md-3
+ .btn-group{:role => "group"}
+ %button.btn.btn-default.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", :type => "button"}
+ Download
+ %span.caret
+ %ul.dropdown-menu
+ %li= link_to 'PDF', download_list_registrant_domains_path(q: params[:q], format: "pdf")
+ %li= link_to 'CSV', download_list_registrant_domains_path(q: params[:q], format: "csv")
+ .col-md-3
+ .col-md-3
+ .col-md-3
+
+
+
%hr
.row
.col-md-12
@@ -8,20 +55,33 @@
%thead
%tr
%th{class: 'col-xs-2'}
- = t(:name)
+ = sort_link(@q, 'name')
%th{class: 'col-xs-2'}
- = t(:registrant)
+ = sort_link(@q, 'registrant_name', t(:registrant))
%th{class: 'col-xs-2'}
- = t(:valid_to)
+ = sort_link(@q, 'valid_to', t(:valid_to))
%th{class: 'col-xs-2'}
- = t(:registrar)
+ = sort_link(@q, 'registrar_name', t(:registrar))
%tbody
- -# - @domains.each do |x|
- -# %tr
- -# %td= link_to(x, admin_domain_path(x))
- -# %td
- -# - if x.registrant
- -# = link_to(x.registrant, [:admin, x.registrant])
+ - @domains.each do |x|
+ %tr
+ %td= link_to(x, registrant_domain_path(x))
+ %td
+ - if x.registrant
+ = link_to(x.registrant, [:registrant, x.registrant]) if x.registrant
+
+ %td= l(x.valid_to, format: :short)
+ %td= link_to(x.registrar, registrant_registrar_path(x.registrar)) if x.registrar
+
+ .row
+ .col-md-6
+ = paginate @domains
+ .col-md-6.text-right
+ .pagination
+ = t(:result_count, count: @domains.total_count)
+
+:coffee
+ $(".js-reset-form").on "click", (e) ->
+ e.preventDefault();
+ window.location = "#{registrant_domains_path}"
- -# %td= l(x.valid_to, format: :short)
- -# %td= link_to(x.registrar, admin_registrar_path(x.registrar)) if x.registrar
diff --git a/app/views/registrant/domains/partials/_admin_contacts.haml b/app/views/registrant/domains/partials/_admin_contacts.haml
new file mode 100644
index 000000000..5e49d3fbc
--- /dev/null
+++ b/app/views/registrant/domains/partials/_admin_contacts.haml
@@ -0,0 +1,22 @@
+- panel_class = @domain.errors.messages[:admin_contacts] ? 'panel-danger' : 'panel-default'
+.panel{class: panel_class}
+ .panel-heading.clearfix
+ = t(:admin_contacts)
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-4'}= t(:name)
+ %th{class: 'col-xs-4'}= t(:id)
+ %th{class: 'col-xs-4'}= t(:email)
+ %tbody
+ - @domain.admin_contacts.each do |ac|
+ %tr
+ %td= link_to(ac, registrant_contact_path(ac))
+ %td= ac.code
+ %td= ac.email
+ - if @domain.errors.messages[:admin_contacts]
+ %tfoot
+ - @domain.errors.messages[:admin_contacts].each do |x|
+ %tr
+ %td{colspan: 4}= x
diff --git a/app/views/registrant/domains/partials/_dnskeys.haml b/app/views/registrant/domains/partials/_dnskeys.haml
new file mode 100644
index 000000000..6d5759e65
--- /dev/null
+++ b/app/views/registrant/domains/partials/_dnskeys.haml
@@ -0,0 +1,25 @@
+- panel_class = @domain.errors.messages[:dnskeys] ? 'panel-danger' : 'panel-default'
+#dnskeys.panel{class: panel_class}
+ .panel-heading.clearfix
+ = t(:dnskeys)
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-1'}= t(:flag)
+ %th{class: 'col-xs-1'}= t(:protocol)
+ %th{class: 'col-xs-1'}= t(:algorithm)
+ %th{class: 'col-xs-9'}= t(:public_key)
+ %tbody
+ - @domain.dnskeys.each do |x|
+ %tr
+ %td= x.flags
+ %td= x.protocol
+ %td= x.alg
+ %td= x.public_key
+ - if @domain.errors.messages[:dnskeys]
+ %tfoot
+ - @domain.errors.messages[:dnskeys].each do |x|
+ %tr
+ %td{colspan: 4}= x
+
diff --git a/app/views/registrant/domains/partials/_general.haml b/app/views/registrant/domains/partials/_general.haml
new file mode 100644
index 000000000..d80c1ce6a
--- /dev/null
+++ b/app/views/registrant/domains/partials/_general.haml
@@ -0,0 +1,32 @@
+.panel.panel-default
+ .panel-heading
+ %h3.panel-title= t(:general)
+ .panel-body
+ %dl.dl-horizontal
+ %dt= t(:name)
+ %dd= @domain.name
+
+ %dt= t(:registered_at)
+ %dd= l(@domain.registered_at)
+
+ %dt= t(:registrar)
+ %dd= link_to(@domain.registrar, registrant_registrar_path(@domain.registrar))
+
+ %dt= t(:authinfo_pw)
+ %dd
+ = text_field_tag :password, @domain.auth_info, readonly: true, class: 'partially-hidden'
+
+ %dt= t(:valid_from)
+ %dd= l(@domain.valid_from)
+
+ %dt= t(:valid_to)
+ %dd= l(@domain.valid_to)
+
+ %dt= t(:outzone_at)
+ %dd= l(@domain.outzone_at)
+
+ %dt= t(:delete_at)
+ %dd= l(@domain.delete_at)
+
+ %dt= t(:force_delete_at)
+ %dd= l(@domain.force_delete_at)
diff --git a/app/views/registrant/domains/partials/_keyrelays.haml b/app/views/registrant/domains/partials/_keyrelays.haml
new file mode 100644
index 000000000..d2d39f6ba
--- /dev/null
+++ b/app/views/registrant/domains/partials/_keyrelays.haml
@@ -0,0 +1,20 @@
+.panel{class: 'panel-default'}
+ .panel-heading.clearfix
+ = t(:keyrelays)
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-4'}= t(:uploaded_at)
+ %th{class: 'col-xs-3'}= t(:expiry)
+ %th{class: 'col-xs-2'}= t(:requester)
+ %th{class: 'col-xs-2'}= t(:accepter)
+ %th{class: 'col-xs-1'}= t(:status)
+ %tbody
+ - @domain.keyrelays.includes([:requester, :accepter]).order(pa_date: :desc).each do |x|
+ %tr
+ %td= link_to(x.pa_date, [:registrar, x])
+ %td= x.expiry
+ %td= link_to(x.requester, [:registrar, x.requester])
+ %td= link_to(x.accepter, [:registrar, x.accepter])
+ %td= x.status
diff --git a/app/views/registrant/domains/partials/_legal_documents.haml b/app/views/registrant/domains/partials/_legal_documents.haml
new file mode 100644
index 000000000..7d740977b
--- /dev/null
+++ b/app/views/registrant/domains/partials/_legal_documents.haml
@@ -0,0 +1,14 @@
+.panel.panel-default
+ .panel-heading.clearfix
+ = t(:legal_documents)
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-8'}= t(:created_at)
+ %th{class: 'col-xs-4'}= t(:type)
+ %tbody
+ - legal_documents.each do |x|
+ %tr
+ %td= link_to(x.created_at, [:registrar, x])
+ %td= x.document_type
diff --git a/app/views/registrant/domains/partials/_nameservers.haml b/app/views/registrant/domains/partials/_nameservers.haml
new file mode 100644
index 000000000..db3ca759a
--- /dev/null
+++ b/app/views/registrant/domains/partials/_nameservers.haml
@@ -0,0 +1,23 @@
+- panel_class = @domain.errors.messages[:nameservers] ? 'panel-danger' : 'panel-default'
+#nameservers.panel{class: panel_class}
+ .panel-heading.clearfix
+ = t(:nameservers)
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-4'}= t(:hostname)
+ %th{class: 'col-xs-4'}= t(:ipv4)
+ %th{class: 'col-xs-4'}= t(:ipv6)
+ %tbody
+ - @domain.nameservers.each do |x|
+ %tr
+ %td= x
+ %td= x.ipv4
+ %td= x.ipv6
+ - if @domain.errors.messages[:nameservers]
+ %tfoot
+ - @domain.errors.messages[:nameservers].each do |x|
+ %tr
+ %td{colspan: 3}= x
+
diff --git a/app/views/registrant/domains/partials/_owner.haml b/app/views/registrant/domains/partials/_owner.haml
new file mode 100644
index 000000000..a7c678d56
--- /dev/null
+++ b/app/views/registrant/domains/partials/_owner.haml
@@ -0,0 +1,19 @@
+.panel.panel-default
+ .panel-heading
+ %h3.panel-title= t(:registrant)
+ .panel-body
+ %dl.dl-horizontal
+ %dt= t(:name)
+ %dd= link_to(@domain.registrant, [:registrar, @domain.registrant])
+
+ %dt= t(:id)
+ %dd= @domain.registrant_code
+
+ %dt= t(:identity_code)
+ %dd= @domain.registrant_ident
+
+ %dt= t(:email)
+ %dd= @domain.registrant_email
+
+ %dt= t(:phone)
+ %dd= @domain.registrant_phone
diff --git a/app/views/registrant/domains/partials/_statuses.haml b/app/views/registrant/domains/partials/_statuses.haml
new file mode 100644
index 000000000..ab8e55e6c
--- /dev/null
+++ b/app/views/registrant/domains/partials/_statuses.haml
@@ -0,0 +1,18 @@
+#domain_statuses.panel.panel-default
+ .panel-heading.clearfix
+ = t(:statuses)
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-6'}= t(:status)
+ %th{class: 'col-xs-6'}= t(:notes)
+ %tbody
+ - @domain.statuses.each do |status|
+ %tr
+ %td
+ - if @domain.pending_json.present? && [DomainStatus::PENDING_UPDATE, DomainStatus::PENDING_DELETE].include?(status)
+ = link_to status, admin_domain_domain_versions_path(@domain.id)
+ - else
+ = status
+ %td= @domain.status_notes[status]
diff --git a/app/views/registrant/domains/partials/_tech_contacts.haml b/app/views/registrant/domains/partials/_tech_contacts.haml
new file mode 100644
index 000000000..12844a41e
--- /dev/null
+++ b/app/views/registrant/domains/partials/_tech_contacts.haml
@@ -0,0 +1,22 @@
+- panel_class = @domain.errors.messages[:tech_contacts] ? 'panel-danger' : 'panel-default'
+#tech_contacts.panel{class: panel_class}
+ .panel-heading.clearfix
+ = t(:tech_contacts)
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-4'}= t(:name)
+ %th{class: 'col-xs-4'}= t(:id)
+ %th{class: 'col-xs-4'}= t(:email)
+ %tbody
+ - @domain.tech_contacts.each do |tc|
+ %tr
+ %td= link_to(tc, registrant_contact_path(tc))
+ %td= tc.code
+ %td= tc.email
+ - if @domain.errors.messages[:tech_contacts]
+ %tfoot
+ - @domain.errors.messages[:tech_contacts].each do |x|
+ %tr
+ %td{colspan: 4}= x
diff --git a/app/views/registrant/domains/show.haml b/app/views/registrant/domains/show.haml
new file mode 100644
index 000000000..0c1ceb48e
--- /dev/null
+++ b/app/views/registrant/domains/show.haml
@@ -0,0 +1,17 @@
+- content_for :actions do
+ = render 'shared/title', name: @domain.name
+
+.row
+ .col-md-6= render 'registrant/domains/partials/general'
+.row
+ .col-md-12= render 'registrant/domains/partials/tech_contacts'
+.row
+ .col-md-12= render 'registrant/domains/partials/admin_contacts'
+.row
+ .col-md-12= render 'registrant/domains/partials/statuses'
+.row
+ .col-md-12= render 'registrant/domains/partials/nameservers'
+.row
+ .col-md-12= render 'registrant/domains/partials/dnskeys'
+.row
+ .col-md-12= render 'registrant/domains/partials/keyrelays'
diff --git a/app/views/registrant/registrants/index.haml b/app/views/registrant/registrants/index.haml
new file mode 100644
index 000000000..11838d1b2
--- /dev/null
+++ b/app/views/registrant/registrants/index.haml
@@ -0,0 +1,112 @@
+= render 'shared/title', name: t(:contacts)
+
+.row
+ .col-md-12
+ = search_form_for [:registrar, @q], html: { style: 'margin-bottom: 0;', class: 'js-form', autocomplete: 'off' } do |f|
+ .row
+ .col-md-3
+ .form-group
+ = f.label :name
+ = f.search_field :name_matches, value: params[:q][:name_matches], class: 'form-control', placeholder: t(:name)
+ .col-md-3
+ .form-group
+ = f.label t(:id)
+ = f.search_field :code_eq, class: 'form-control', placeholder: t(:id)
+ .col-md-3
+ .form-group
+ = f.label t(:ident)
+ = f.search_field :ident_matches, class: 'form-control', placeholder: t(:ident)
+ .col-md-3
+ .form-group
+ = label_tag t(:ident_type)
+ = select_tag '[q][ident_type_eq]', options_for_select(Contact::IDENT_TYPES, params[:q][:ident_type_eq]), { include_blank: true, placeholder: t(:choose), class: 'form-control selectize' }
+ .row
+ .col-md-3
+ .form-group
+ = f.label t(:email)
+ = f.search_field :email_matches, class: 'form-control', placeholder: t(:email)
+ .col-md-3
+ .form-group
+ = label_tag t(:country)
+ = select_tag '[q][country_code_eq]', SortedCountry.all_options(params[:q][:country_code_eq]), { include_blank: true, placeholder: t(:choose), class: 'form-control selectize' }
+ .col-md-3
+ .form-group
+ = f.label t(:is_registrant)
+ %div
+ = f.check_box :registrant_domains_id_not_null
+ .col-md-3
+ .form-group
+ = label_tag t(:contact_type)
+ = select_tag '[q][domain_contacts_type_in]', options_for_select([['admin', 'AdminDomainContact'], ['tech', 'TechDomainContact']], params[:q][:domain_contacts_type_in]), { multiple: true, placeholder: t(:choose), class: 'form-control js-combobox' }
+ .row
+ .col-md-3
+ .form-group
+ = f.label t(:registrar)
+ = f.select :registrar_id_eq, Registrar.all.map { |x| [x, x.id] }, { include_blank: true }, class: 'form-control selectize', placeholder: t(:choose)
+ .col-md-3
+ .form-group
+ = f.label t(:created_at_from)
+ = f.search_field :created_at_gteq, value: params[:q][:created_at_gteq], class: 'form-control datepicker', placeholder: t(:created_at_from)
+ .col-md-3
+ .form-group
+ = f.label t(:created_at_until)
+ = f.search_field :created_at_lteq, value: params[:q][:created_at_lteq], class: 'form-control datepicker', placeholder: t(:created_at_until)
+ .col-md-3
+ .form-group
+ = f.label t(:updated_at)
+ = f.search_field :updated_at_gteq, value: params[:q][:updated_at_gteq], class: 'form-control datepicker', placeholder: t(:updated_at)
+ .row
+ .col-md-6
+ .form-group
+ = label_tag t(:status)
+ = select_tag :statuses_contains, options_for_select(Contact::STATUSES, params[:statuses_contains]), { multiple: true, placeholder: t(:choose), class: 'form-control js-combobox' }
+ .col-md-3
+ .form-group
+ = label_tag t(:results_per_page)
+ = text_field_tag :results_per_page, params[:results_per_page], class: 'form-control', placeholder: t(:results_per_page)
+ .col-md-3{style: 'padding-top: 25px;'}
+ %button.btn.btn-primary
+
+ %span.glyphicon.glyphicon-search
+
+ %button.btn.btn-default.js-reset-form
+ = t(:clear_fields)
+%hr
+.row
+ .col-md-12
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-2'}
+ = sort_link(@q, 'name', t(:name))
+ %th{class: 'col-xs-2'}
+ = sort_link(@q, 'code', t(:id))
+ %th{class: 'col-xs-2'}
+ = sort_link(@q, 'ident', t(:ident))
+ %th{class: 'col-xs-2'}
+ = sort_link(@q, 'email', t(:created_at))
+ %th{class: 'col-xs-2'}
+ = sort_link(@q, 'registrar_name', t(:registrar))
+ %tbody
+ - @contacts.each do |contact|
+ %tr
+ %td= link_to(contact, registrar_contact_path(contact))
+ %td= contact.code
+ %td= ident_for(contact)
+ %td= l(contact.created_at, format: :short)
+ %td
+ - if contact.registrar
+ = link_to(contact.registrar, registrar_registrar_path(contact.registrar))
+
+.row
+ .col-md-6
+ = paginate @contacts
+ .col-md-6.text-right
+ .pagination
+ = t(:result_count, count: @contacts.total_count)
+
+:coffee
+ $(".js-reset-form").on "click", (e) ->
+ e.preventDefault();
+ window.location = "#{registrar_contacts_path}"
diff --git a/app/views/registrant/registrants/show.haml b/app/views/registrant/registrants/show.haml
new file mode 100644
index 000000000..5b2a527ca
--- /dev/null
+++ b/app/views/registrant/registrants/show.haml
@@ -0,0 +1,75 @@
+= render 'shared/title', name: @contact.name
+
+.row
+ .col-md-6
+ .panel.panel-default
+ .panel-heading
+ %h3.panel-title= t(:general)
+ .panel-body
+ %dl.dl-horizontal
+ %dt= t(:id)
+ %dd= @contact.code
+
+ %dt= t(:authinfo_pw)
+ %dd
+ = text_field_tag :auth_info, @contact.auth_info, readonly: true, class: 'partially-hidden'
+
+ %br
+
+ %dt= t(:ident)
+ %dd= ident_for(@contact)
+
+ %dt= t(:email)
+ %dd= @contact.email
+
+ %dt= t(:phone)
+ %dd= @contact.phone
+
+ - if @contact.fax
+ %dt= t(:fax)
+ %dd= @contact.fax
+
+ %br
+
+ %dt= t(:created)
+ %dd
+ = l(@contact.created_at, format: :short)
+ by
+ = creator_link(@contact)
+
+ %dt= t(:updated)
+ %dd
+ = l(@contact.updated_at, format: :short)
+ by
+ = updator_link(@contact)
+
+ %dt= t(:registrar)
+ %dd
+ - if @contact.registrar.present?
+ = link_to(@contact.registrar, registrant_registrar_path(@contact.registrar)) if @contact.registrar
+
+ .col-md-6
+ .panel.panel-default
+ .panel-heading
+ %h3.panel-title= t(:contact)
+ .panel-body
+ %dl.dl-horizontal
+ %dl.dl-horizontal
+ - if @contact.org_name.present?
+ %dt= t(:org_name)
+ %dd= @contact.org_name
+
+ %dt= t(:street)
+ %dd= @contact.street.to_s.gsub("\n", '
').html_safe
+
+ %dt= t(:city)
+ %dd= @contact.city
+
+ %dt= t(:zip)
+ %dd= @contact.zip
+
+ %dt= t(:state)
+ %dd= @contact.state
+
+ %dt= t(:country)
+ %dd= @contact.country
\ No newline at end of file
diff --git a/app/views/registrant/registrars/index.haml b/app/views/registrant/registrars/index.haml
new file mode 100644
index 000000000..0489bcf52
--- /dev/null
+++ b/app/views/registrant/registrars/index.haml
@@ -0,0 +1,21 @@
+- content_for :actions do
+ = render 'shared/title', name: t(:registrars)
+
+.row
+ .col-md-12
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-6'}
+ = sort_link(@q, 'name')
+ %th{class: 'col-xs-6'}
+ = sort_link(@q, 'reg_no', t(:reg_no))
+ %tbody
+ - @registrars.each do |x|
+ %tr
+ %td= link_to(x, [:registrar, x])
+ %td= x.reg_no
+.row
+ .col-md-12
+ = paginate @registrars
diff --git a/app/views/registrant/registrars/show.haml b/app/views/registrant/registrars/show.haml
new file mode 100644
index 000000000..ed5c72b29
--- /dev/null
+++ b/app/views/registrant/registrars/show.haml
@@ -0,0 +1,53 @@
+= render 'shared/title', name: @registrar.name
+
+- if @registrar.errors.any?
+ - @registrar.errors.each do |attr, err|
+ = err
+ %br
+- if @registrar.errors.any?
+ %hr
+.row
+ .col-md-6
+ .panel.panel-default
+ .panel-heading
+ %h3.panel-title= t(:general)
+ .panel-body
+ %dl.dl-horizontal
+ %dt= t(:name)
+ %dd= @registrar.name
+
+ %dt= t(:reg_no)
+ %dd= @registrar.reg_no
+
+ %dt= t(:vat_no)
+ %dd= @registrar.vat_no
+
+ %dt= t(:reference_no)
+ %dd= @registrar.reference_no
+
+ %dt= t(:id)
+ %dd= @registrar.code
+
+ .col-md-6
+ .panel.panel-default
+ .panel-heading
+ %h3.panel-title= t(:contact)
+ .panel-body
+ %dl.dl-horizontal
+ %dt= t(:country)
+ %dd= @registrar.country
+
+ %dt= t(:address)
+ %dd= @registrar.address
+
+ %dt= t(:contact_phone)
+ %dd= @registrar.phone
+
+ %dt= t(:contact_email)
+ %dd= @registrar.email
+
+ %dt= t(:billing_address)
+ %dd= @registrar.billing_address
+
+ %dt= t(:billing_email)
+ %dd= @registrar.billing_email
diff --git a/app/views/registrant/whois/index.haml b/app/views/registrant/whois/index.haml
index 3e390eaf3..3d95af638 100644
--- a/app/views/registrant/whois/index.haml
+++ b/app/views/registrant/whois/index.haml
@@ -17,5 +17,5 @@
%span.glyphicon.glyphicon-search
%hr
- - if @results
- = @results
+ - if @domain
+ %pre= @domain.body
\ No newline at end of file
diff --git a/config/application-example.yml b/config/application-example.yml
index cf6e26357..4db92097f 100644
--- a/config/application-example.yml
+++ b/config/application-example.yml
@@ -88,6 +88,16 @@ repp_url: 'https://repp.gitlab.eu/repp/v1/'
#
restful_whois_url: 'https://restful-whois.example.com'
+#
+# Estonian Business Registry
+#
+# config/secrets.yml --- arireg: {username, password}
+arireg_username: 'kasutaja'
+arireg_password: 'parool'
+# config/environments/production.rb --- Soap::Arireg.wsdl, Soap::Arireg.host
+arireg_wsdl: 'lib/schemas/testariport.wsdl' # https://demo-ariregxml.rik.ee:447/testariport/?wsdl
+#arireg_wsdl: 'lib/schemas/ariport.wsdl' # https://ariregxml.rik.ee/ariport/?wsdl
+arireg_host: 'https://demo-ariregxml.rik.ee:447' # https://ariregxml.rik.ee/
#
# REGISTRAR AND REGISTRANT
diff --git a/config/application.rb b/config/application.rb
index 7734cc6e9..2121039dc 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -7,6 +7,8 @@ require 'action_controller/railtie'
require 'action_mailer/railtie'
require 'action_view/railtie'
require 'sprockets/railtie'
+require 'csv'
+require 'rails/all'
# require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
diff --git a/config/initializers/initial_settings.rb b/config/initializers/initial_settings.rb
index 1b25ddeb3..eb333943f 100644
--- a/config/initializers/initial_settings.rb
+++ b/config/initializers/initial_settings.rb
@@ -28,6 +28,8 @@ if con.present? && con.table_exists?('settings')
Setting.save_default(:client_side_status_editing_enabled, false)
+ Setting.save_default(:days_to_keep_business_registry_cache, 2)
+
Setting.save_default(:invoice_number_min, 131050)
Setting.save_default(:invoice_number_max, 149999)
Setting.save_default(:days_to_keep_invoices_active, 30)
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 08c70737f..db0ca37ce 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -537,7 +537,8 @@ en:
switch_to: Switch to
admin_menu: Admin
domain_transfer_was_approved: 'Domain transfer was approved, associated contacts were: %{contacts} and registrant was %{registrant}'
-
+ business_registry_service_not_available: "Business Registry service Ärireg is not available"
+
# DEPP
activemodel:
errors:
diff --git a/config/routes.rb b/config/routes.rb
index 86bdccaa9..e0a331256 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -103,6 +103,12 @@ Rails.application.routes.draw do
namespace :registrant do
root 'domains#index'
+ resources :domains do
+ collection do
+ get :download_list
+ end
+ end
+
# resources :invoices do
# member do
# get 'download_pdf'
@@ -141,6 +147,17 @@ Rails.application.routes.draw do
end
end
+ resources :registrars do
+ resources :api_users
+ resources :white_ips
+ collection do
+ get :search
+ end
+ end
+
+ resources :registrants
+ resources :contacts
+
resources :whois
# resources :contacts do
# member do
diff --git a/db/migrate/20151209122816_create_business_registry_caches.rb b/db/migrate/20151209122816_create_business_registry_caches.rb
new file mode 100644
index 000000000..3d7766a60
--- /dev/null
+++ b/db/migrate/20151209122816_create_business_registry_caches.rb
@@ -0,0 +1,13 @@
+class CreateBusinessRegistryCaches < ActiveRecord::Migration
+ def change
+ create_table :business_registry_caches do |t|
+ t.string :ident
+ t.string :ident_country_code
+ t.datetime :retrieved_on
+ t.string :associated_businesses, array: true
+ t.timestamps null: false
+ end
+
+ add_index :business_registry_caches, :ident
+ end
+end
diff --git a/lib/schemas/ariport.wsdl b/lib/schemas/ariport.wsdl
new file mode 100644
index 000000000..7525c9227
--- /dev/null
+++ b/lib/schemas/ariport.wsdl
@@ -0,0 +1,510 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Teenuste nimekiri
+
+
+
+
+
+
+ Adapteri test
+
+
+
+
+
+
+ Ettevõtjaga seotud dokumentide loetelu päring
+
+
+
+
+
+
+ Ettevõtja esmakannete päring
+
+
+
+
+
+
+ Ettevõtja muudatuste loetelu tasuline päring
+
+
+
+
+
+
+ Ettevotja rekvisiitide päring
+
+
+
+
+
+
+ Ettevotja rekvisiitide fail
+
+
+
+
+
+
+ Isikute otsing
+
+
+
+
+
+
+ Klassifikaatorite päring
+
+
+
+
+
+
+ Ettevõtja majandusaasta aruande päring
+
+
+
+
+
+
+ Ettevõtja majandusaasta aruande loetelu päring
+
+
+
+
+
+
+ Ettevõtja detailandmete päring v5
+
+
+
+
+
+
+ E-notar: toimiku dokumendi sisu
+
+
+
+
+
+
+ Ettevõtja lihtandmete päring v5
+
+
+
+
+
+
+ Ettevõtja lihtandmete päring tasuta
+
+
+
+
+
+
+ Esindusõiguste päring v3
+
+
+
+
+
+
+ Esindusõiguste päring v4
+
+
+
+
+
+
+ Visuaalse Äriregistri ettevõtete-isikute vaheliste seoste päring
+
+
+
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+
+
+
+
+ Äriregister_uus
+
+
+
+
diff --git a/lib/schemas/testariport.wsdl b/lib/schemas/testariport.wsdl
new file mode 100644
index 000000000..25e3818b2
--- /dev/null
+++ b/lib/schemas/testariport.wsdl
@@ -0,0 +1,510 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Teenuste nimekiri
+
+
+
+
+
+
+ Adapteri test
+
+
+
+
+
+
+ Ettevõtjaga seotud dokumentide loetelu päring
+
+
+
+
+
+
+ Ettevõtja esmakannete päring
+
+
+
+
+
+
+ Ettevõtja muudatuste loetelu tasuline päring
+
+
+
+
+
+
+ Ettevotja rekvisiitide päring
+
+
+
+
+
+
+ Ettevotja rekvisiitide fail
+
+
+
+
+
+
+ Isikute otsing
+
+
+
+
+
+
+ Klassifikaatorite päring
+
+
+
+
+
+
+ Ettevõtja majandusaasta aruande päring
+
+
+
+
+
+
+ Ettevõtja majandusaasta aruande loetelu päring
+
+
+
+
+
+
+ Ettevõtja detailandmete päring v5
+
+
+
+
+
+
+ E-notar: toimiku dokumendi sisu
+
+
+
+
+
+
+ Ettevõtja lihtandmete päring v5
+
+
+
+
+
+
+ Ettevõtja lihtandmete päring tasuta
+
+
+
+
+
+
+ Esindusõiguste päring v3
+
+
+
+
+
+
+ Esindusõiguste päring v4
+
+
+
+
+
+
+ Visuaalse Äriregistri ettevõtete-isikute vaheliste seoste päring
+
+
+
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+ v1
+
+
+
+
+
+
+
+
+
+
+
+ Äriregister_uus
+
+
+
+