diff --git a/.codeclimate.yml b/.codeclimate.yml index d079d891f..33801cc17 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -7,14 +7,19 @@ prepare: plugins: brakeman: enabled: true + checks: + mass_assign_permit!: + enabled: false bundler-audit: enabled: true duplication: enabled: true config: languages: - - ruby - - javascript + ruby: + mass_threshold: 100 + javascript: + mass_threshold: 100 eslint: enabled: true channel: eslint-5 @@ -26,6 +31,9 @@ plugins: rubocop: enabled: true channel: rubocop-0-74 + checks: + Rubocop/Style/ClassAndModuleChildren: + enabled: false checks: method-lines: config: diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index eea0ccc03..8880e83d4 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -17,7 +17,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-18.04] - ruby: [2.6, 2.7 ] + ruby: [ 2.7 ] runs-on: ${{ matrix.os }} continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }} steps: @@ -100,11 +100,6 @@ jobs: - name: Give test coverage reporter executable permissions run: chmod +x cc-test-reporter - - uses: actions/download-artifact@v1 - with: - name: coverage-2.6 - path: coverage - - uses: actions/download-artifact@v1 with: name: coverage-2.7 diff --git a/.ruby-version b/.ruby-version index 57cf282eb..37c2961c2 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.6.5 +2.7.2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 50e8560d6..b5c2e19cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,81 @@ +12.03.2021 +* Removed old classnames from notifications [#1878](https://github.com/internetee/registry/pull/1878) + +11.03.2021 +* Account activity in registrar and REPP now return balance with each record [#1819](https://github.com/internetee/registry/issues/1819) +* Fixed CookieOverflow error with large authentication service keys [#1879](https://github.com/internetee/registry/pull/1879) + +10.03.2021 +* Registrant API returns full contact details for admin contacts [#1876](https://github.com/internetee/registry/pull/1876) + +09.03.2021 +* AWS message id saving over API [#1877](https://github.com/internetee/registry/pull/1877) +* Enabled Zeitwerk autoloader [#1872](https://github.com/internetee/registry/issues/1872) + +04.03.2021 +* Removed old registrant portal from the project [#1826](https://github.com/internetee/registry/issues/1826) + +03.03.2021 +* Email notification is sent in case of pendingupdate expiry [#897](https://github.com/internetee/registry/issues/897) + +26.02.2021 +* Domain delete is not affected by updateProhibited [#1844](https://github.com/internetee/registry/issues/1844) +* Registrant API fix for handling eidas personal identificators [#1864](https://github.com/internetee/registry/pull/1864) + +23.02.2021 +* UpdateProhibited status affects bulk actions in REPP [#1818](https://github.com/internetee/registry/issues/1818) +* Registrant api domain request now excludes tech only domains by default [#1836](https://github.com/internetee/registry/pull/1836) + +22.02.2021 +* serverDeleteProhibited prohibts delete action [#1849](https://github.com/internetee/registry/issues/1849) + +19.02.2021 +* Update prohibited staatus is kept after renew [#1843](https://github.com/internetee/registry/issues/1843) +* Fixed clientHold and serverManualInzone status conflict issue [#1845](https://github.com/internetee/registry/issues/1845) +* Replacing registrant object with another that has the same ident data set does not require registrant verification [#1852](https://github.com/internetee/registry/issues/1852) + +11.02.2021 +* Poll messages on locking and unlocking a domain [#1828](https://github.com/internetee/registry/issues/1828) +* Registrar's prefix is now checked and added to contact id for info and check requests [#1832](https://github.com/internetee/registry/issues/1832) + +10.02.2021 +* Admin contact bulk change option for registrars [#1764](https://github.com/internetee/registry/issues/1764) +* Option to remove email addresses from AWS SES Supression list [#1839](https://github.com/internetee/registry/issues/1839) +* Added separate key for bounce API [#1842](https://github.com/internetee/registry/pull/1842) + +09.02.2021 +* Added new endpoint for WHOIS contact requests [#1794](https://github.com/internetee/registry/pull/1794) + +05.02.2021 +* Fixed IPv4 empty string issue in case of IPv6 only entries for IP whitelist [#1833](https://github.com/internetee/registry/issues/1833) + +02.02.2021 +* Fixed updateProhibited status not affecting bulk tech contact change operation [#1820](https://github.com/internetee/registry/pull/1820) + +01.02.2021 +* Improved tests for admin interface [#1805](https://github.com/internetee/registry/pull/1805) + +28.01.2021 +* Fixed transfer with shared admin and tech contacts [#1808](https://github.com/internetee/registry/issues/1808) +* Improved error handling with double admin/tech contacts [#1758](https://github.com/internetee/registry/issues/1758) +* Added CSV export option to admin [#1775](https://github.com/internetee/registry/issues/1775) +* Improved DNSSEC key validation for illegal characters [#1790](https://github.com/internetee/registry/issues/1790) +* Fix for whois record creation issue on releasing domain to auction [#1139](https://github.com/internetee/registry/issues/1139) +* Fix for handling malformed request frames [#1825](https://github.com/internetee/registry/issues/1825) +* Improved registrar account activity tests [#1824](https://github.com/internetee/registry/pull/1824) + +27.01.2021 +* Figaro update to 1.2.0 [#1823](https://github.com/internetee/registry/pull/1823) + +26.01.2021 +* Ruby update to 2.7 [#1791](https://github.com/internetee/registry/issues/1791) + +21.01.2021 +* Registrant API: optimised contact linking [#1807](https://github.com/internetee/registry/pull/1807) + +20.01.2021 +* Fixed legaldoc assignment issue on registrant confirmation [#1806](https://github.com/internetee/registry/pull/1806) + 14.01.2021 * Fixed IDN and punycode support for REPP domain transfer_info request [#1801](https://github.com/internetee/registry/issues/1801) diff --git a/Dockerfile b/Dockerfile index 5d241eeef..97b0452e1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM internetee/ruby:2.6-buster +FROM internetee/ruby:2.7-buster RUN mkdir -p /opt/webapps/app/tmp/pids WORKDIR /opt/webapps/app diff --git a/Gemfile b/Gemfile index 9bbcba254..82a0b4666 100644 --- a/Gemfile +++ b/Gemfile @@ -9,7 +9,7 @@ gem 'rest-client' gem 'uglifier' # load env -gem 'figaro', '1.1.1' +gem 'figaro', '~> 1.2' # model related gem 'activerecord-import' @@ -92,3 +92,5 @@ group :test do gem 'webdrivers' gem 'webmock' end + +gem 'aws-sdk-sesv2', '~> 1.16' diff --git a/Gemfile.lock b/Gemfile.lock index 2a0bb55b1..08daf4226 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -148,6 +148,18 @@ GEM attr_required (1.0.1) autoprefixer-rails (10.0.0.2) execjs + aws-eventstream (1.1.0) + aws-partitions (1.424.0) + aws-sdk-core (3.112.0) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.239.0) + aws-sigv4 (~> 1.1) + jmespath (~> 1.0) + aws-sdk-sesv2 (1.16.0) + aws-sdk-core (~> 3, >= 3.112.0) + aws-sigv4 (~> 1.1) + aws-sigv4 (1.2.2) + aws-eventstream (~> 1, >= 1.0.2) bcrypt (3.1.16) bindata (2.4.8) bootsnap (1.4.8) @@ -202,8 +214,8 @@ GEM erubis (2.7.0) execjs (2.7.0) ffi (1.13.1) - figaro (1.1.1) - thor (~> 0.14) + figaro (1.2.0) + thor (>= 0.14.0, < 2) globalid (0.4.2) activesupport (>= 4.2.0) gyoku (1.3.1) @@ -226,6 +238,7 @@ GEM i18n_data (0.10.0) isikukood (0.1.2) iso8601 (0.12.1) + jmespath (1.4.0) jquery-rails (4.4.0) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) @@ -484,6 +497,7 @@ DEPENDENCIES active_interaction (~> 3.8) activerecord-import airbrake + aws-sdk-sesv2 (~> 1.16) bootsnap (>= 1.1.0) bootstrap-sass (~> 3.4) cancancan @@ -502,7 +516,7 @@ DEPENDENCIES e_invoice! epp! epp-xml (= 1.1.0)! - figaro (= 1.1.1) + figaro (~> 1.2) haml (~> 5.0) isikukood iso8601 (= 0.12.1) diff --git a/app/assets/javascripts/admin/application.coffee b/app/assets/javascripts/admin/application.coffee index 4c7e6acb2..a149d89cf 100644 --- a/app/assets/javascripts/admin/application.coffee +++ b/app/assets/javascripts/admin/application.coffee @@ -8,6 +8,8 @@ $(window).load -> $('[data-toggle="popover"]').popover() + $('[data-toggle="tooltip"]').tooltip() + # doublescroll $('[data-doublescroll]').doubleScroll({ onlyIfScroll: false, diff --git a/app/controllers/admin/contact_versions_controller.rb b/app/controllers/admin/contact_versions_controller.rb index 834353cf4..9638b341f 100644 --- a/app/controllers/admin/contact_versions_controller.rb +++ b/app/controllers/admin/contact_versions_controller.rb @@ -2,12 +2,12 @@ module Admin class ContactVersionsController < BaseController include ObjectVersionsHelper - load_and_authorize_resource + load_and_authorize_resource class: Version::ContactVersion def index params[:q] ||= {} - @q = ContactVersion.search(params[:q]) + @q = Version::ContactVersion.search(params[:q]) @versions = @q.result.page(params[:page]) search_params = params[:q].deep_dup @@ -23,7 +23,7 @@ module Admin end end - versions = ContactVersion.includes(:item).where(whereS).order(created_at: :desc, id: :desc) + versions = Version::ContactVersion.includes(:item).where(whereS).order(created_at: :desc, id: :desc) @q = versions.search(params[:q]) @versions = @q.result.page(params[:page]) @versions = @versions.per(params[:results_per_page]) if params[:results_per_page].to_i.positive? @@ -32,8 +32,8 @@ module Admin def show per_page = 7 - @version = ContactVersion.find(params[:id]) - @versions = ContactVersion.where(item_id: @version.item_id).order(created_at: :desc, id: :desc) + @version = Version::ContactVersion.find(params[:id]) + @versions = Version::ContactVersion.where(item_id: @version.item_id).order(created_at: :desc, id: :desc) @versions_map = @versions.all.map(&:id) # what we do is calc amount of results until needed version @@ -49,7 +49,7 @@ module Admin end def search - render json: ContactVersion.search_by_query(params[:q]) + render json: Version::ContactVersion.search_by_query(params[:q]) end def create_where_string(key, value) diff --git a/app/controllers/admin/domain_versions_controller.rb b/app/controllers/admin/domain_versions_controller.rb index b6245f6ea..2d054f73d 100644 --- a/app/controllers/admin/domain_versions_controller.rb +++ b/app/controllers/admin/domain_versions_controller.rb @@ -2,12 +2,12 @@ module Admin class DomainVersionsController < BaseController include ObjectVersionsHelper - load_and_authorize_resource + load_and_authorize_resource class: Version::DomainVersion def index params[:q] ||= {} - @q = DomainVersion.includes(:item).search(params[:q]) + @q = Version::DomainVersion.includes(:item).search(params[:q]) @versions = @q.result.page(params[:page]) search_params = params[:q].deep_dup @@ -40,7 +40,7 @@ module Admin whereS += " AND object->>'registrar_id' IN (#{registrars.map { |r| "'#{r.id.to_s}'" }.join ','})" if registrars.present? whereS += " AND 1=0" if registrars == [] - versions = DomainVersion.includes(:item).where(whereS).order(created_at: :desc, id: :desc) + versions = Version::DomainVersion.includes(:item).where(whereS).order(created_at: :desc, id: :desc) @q = versions.search(params[:q]) @versions = @q.result.page(params[:page]) @versions = @versions.per(params[:results_per_page]) if params[:results_per_page].to_i.positive? @@ -50,8 +50,8 @@ module Admin def show per_page = 7 - @version = DomainVersion.find(params[:id]) - @versions = DomainVersion.where(item_id: @version.item_id).order(created_at: :desc, id: :desc) + @version = Version::DomainVersion.find(params[:id]) + @versions = Version::DomainVersion.where(item_id: @version.item_id).order(created_at: :desc, id: :desc) @versions_map = @versions.all.map(&:id) # what we do is calc amount of results until needed version @@ -67,7 +67,7 @@ module Admin end def search - render json: DomainVersion.search_by_query(params[:q]) + render json: Version::DomainVersion.search_by_query(params[:q]) end def create_where_string(key, value) diff --git a/app/controllers/admin/domains_controller.rb b/app/controllers/admin/domains_controller.rb index 4a8e5961e..3e2d78671 100644 --- a/app/controllers/admin/domains_controller.rb +++ b/app/controllers/admin/domains_controller.rb @@ -27,8 +27,17 @@ module Admin params[:q][:name_matches] = n_cache # we don't want to show wildcards in search form end end - @domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i.positive? + + respond_to do |format| + format.html do + @domains + end + format.csv do + raw_csv = @domains.to_csv + send_data raw_csv, filename: 'domains.csv', type: "#{Mime[:csv]}; charset=utf-8" + end + end end def show diff --git a/app/controllers/api/v1/base_controller.rb b/app/controllers/api/v1/base_controller.rb index b62b3e063..6ee986a48 100644 --- a/app/controllers/api/v1/base_controller.rb +++ b/app/controllers/api/v1/base_controller.rb @@ -11,7 +11,7 @@ module Api end def authenticate_shared_key - api_key = "Basic #{ENV['api_shared_key']}" + api_key = "Basic #{ENV['rwhois_internal_api_shared_key']}" head(:unauthorized) unless api_key == request.authorization end diff --git a/app/controllers/api/v1/bounces_controller.rb b/app/controllers/api/v1/bounces_controller.rb index fd10a3398..de2814250 100644 --- a/app/controllers/api/v1/bounces_controller.rb +++ b/app/controllers/api/v1/bounces_controller.rb @@ -1,7 +1,7 @@ module Api module V1 class BouncesController < BaseController - before_action :authenticate_shared_key + before_action :validate_shared_key_integrity # POST api/v1/bounces/ def create @@ -20,6 +20,13 @@ module Api params.require(:data) end + + private + + def validate_shared_key_integrity + api_key = "Basic #{ENV['rwhois_bounces_api_shared_key']}" + head(:unauthorized) unless api_key == request.authorization + end end end end diff --git a/app/controllers/api/v1/contact_requests_controller.rb b/app/controllers/api/v1/contact_requests_controller.rb new file mode 100644 index 000000000..1ef73e9ef --- /dev/null +++ b/app/controllers/api/v1/contact_requests_controller.rb @@ -0,0 +1,38 @@ +module Api + module V1 + class ContactRequestsController < BaseController + before_action :authenticate_shared_key + + # POST api/v1/contact_requests/ + def create + return head(:bad_request) if contact_request_params[:email].blank? + + contact_request = ContactRequest.save_record(contact_request_params) + render json: contact_request, status: :created + rescue StandardError + head(:bad_request) + end + + def update + return head(:bad_request) if params[:id].blank? + + process_id(params[:id]) + end + + def process_id(id) + record = ContactRequest.find_by(id: id) + return :not_found unless record + + record.update_record(contact_request_params) + render json: record, status: :ok + rescue StandardError + head :bad_request + end + + def contact_request_params + params.require(:contact_request).permit(:email, :whois_record_id, :name, :status, :ip, + :message_id) + end + end + end +end diff --git a/app/controllers/api/v1/registrant/auth_controller.rb b/app/controllers/api/v1/registrant/auth_controller.rb index 03dfa45f3..728ef696d 100644 --- a/app/controllers/api/v1/registrant/auth_controller.rb +++ b/app/controllers/api/v1/registrant/auth_controller.rb @@ -19,6 +19,9 @@ module Api token = create_token(user) if token + msg = "Bearer for #{eid_params[:first_name]} #{eid_params[:last_name]} " \ + "(#{eid_params[:ident]}) - '#{token[:access_token]}'" + ToStdout.msg(msg) unless Rails.env.production? render json: token else render json: { errors: [{ base: ['Cannot create generate session token'] }] } @@ -37,7 +40,7 @@ module Api obj.require(key) end - params.permit(required_params) + params.permit(required_params + [:country_code]) end def create_token(user) diff --git a/app/controllers/api/v1/registrant/contacts_controller.rb b/app/controllers/api/v1/registrant/contacts_controller.rb index e11458ff8..ec59ed83f 100644 --- a/app/controllers/api/v1/registrant/contacts_controller.rb +++ b/app/controllers/api/v1/registrant/contacts_controller.rb @@ -24,7 +24,7 @@ module Api end def show - contact = current_user_contacts.find_by(uuid: params[:uuid]) + contact = representable_contact(params[:uuid]) links = params[:links] == 'true' if contact @@ -91,6 +91,22 @@ module Api private + def representable_contact(uuid) + country = current_registrant_user.country.alpha2 + contact = Contact.find_by(uuid: uuid, ident: current_registrant_user.ident, + ident_type: 'priv', ident_country_code: country) + return contact if contact + + Contact.find_by(uuid: uuid, ident_type: 'org', ident: company_codes, + ident_country_code: country) + rescue CompanyRegister::NotAvailableError + nil + end + + def company_codes + current_registrant_user.companies.collect(&:registration_number) + end + def current_user_contacts current_registrant_user.contacts(representable: false) rescue CompanyRegister::NotAvailableError diff --git a/app/controllers/api/v1/registrant/domains_controller.rb b/app/controllers/api/v1/registrant/domains_controller.rb index 73b534598..94d2c865a 100644 --- a/app/controllers/api/v1/registrant/domains_controller.rb +++ b/app/controllers/api/v1/registrant/domains_controller.rb @@ -4,6 +4,8 @@ module Api module V1 module Registrant class DomainsController < ::Api::V1::Registrant::BaseController + before_action :set_tech_flag, only: [:show] + def index limit = params[:limit] || 200 offset = params[:offset] || 0 @@ -25,7 +27,8 @@ module Api serializer.to_json end - render json: { count: domains.count, domains: serialized_domains } + render json: { total: current_user_domains_total_count, count: domains.count, + domains: serialized_domains } end def show @@ -41,10 +44,22 @@ module Api private - def current_user_domains - current_registrant_user.domains + def set_tech_flag + # current_user_domains scope depends on tech flag + # However, if it's not present, tech contact can not see specific domain entry at all. + params.merge!(tech: 'true') + end + + def current_user_domains_total_count + current_registrant_user.domains.count rescue CompanyRegister::NotAvailableError - current_registrant_user.direct_domains + current_registrant_user.direct_domains.count + end + + def current_user_domains + current_registrant_user.domains(admin: params[:tech] != 'true') + rescue CompanyRegister::NotAvailableError + current_registrant_user.direct_domains(admin: params[:tech] != 'true') end end end diff --git a/app/controllers/epp/contacts_controller.rb b/app/controllers/epp/contacts_controller.rb index 85305213b..65354ff48 100644 --- a/app/controllers/epp/contacts_controller.rb +++ b/app/controllers/epp/contacts_controller.rb @@ -14,7 +14,7 @@ module Epp authorize! :check, Epp::Contact ids = params[:parsed_frame].css('id').map(&:text) - @results = Epp::Contact.check_availability(ids) + @results = Epp::Contact.check_availability(ids, reg: current_user.registrar.code) render_epp_response '/epp/contacts/check' end @@ -93,7 +93,11 @@ module Epp def find_contact code = params[:parsed_frame].css('id').text.strip.upcase - @contact = Epp::Contact.find_by!(code: code) + reg_code = current_user.registrar.code.upcase + arr = [code, "#{reg_code}:#{code}", "CID:#{code}", "CID:#{reg_code}:#{code}"] + + contact = arr.find { |c| Epp::Contact.find_by(code: c).present? } + @contact = Epp::Contact.find_by!(code: contact || code) end # diff --git a/app/controllers/epp/polls_controller.rb b/app/controllers/epp/polls_controller.rb index 060931796..a93fa300d 100644 --- a/app/controllers/epp/polls_controller.rb +++ b/app/controllers/epp/polls_controller.rb @@ -12,9 +12,11 @@ module Epp @notification = current_user.unread_notifications.order('created_at DESC').take render_epp_response 'epp/poll/poll_no_messages' and return unless @notification + if @notification.attached_obj_type && @notification.attached_obj_id begin - @object = Object.const_get(@notification.attached_obj_type).find(@notification.attached_obj_id) + @object = object_by_type(@notification.attached_obj_type) + .find(@notification.attached_obj_id) rescue => problem # the data model might be inconsistent; or ... # this could happen if the registrar does not dequeue messages, and then the domain was deleted @@ -31,6 +33,12 @@ module Epp render_epp_response 'epp/poll/poll_req' end + def object_by_type(object_type) + Object.const_get(object_type) + rescue NameError + Object.const_get("Version::#{object_type}") + end + def ack_poll @notification = current_user.unread_notifications.find_by(id: params[:parsed_frame].css('poll').first['msgID']) diff --git a/app/controllers/registrant/contacts_controller.rb b/app/controllers/registrant/contacts_controller.rb deleted file mode 100644 index 49070ebde..000000000 --- a/app/controllers/registrant/contacts_controller.rb +++ /dev/null @@ -1,115 +0,0 @@ -class Registrant::ContactsController < RegistrantController - helper_method :domain - helper_method :fax_enabled? - helper_method :domain_filter_params - skip_authorization_check only: %i[edit update] - before_action :set_contact, only: [:show] - - def show - @requester_contact = Contact.find_by(ident: current_registrant_user.ident) - authorize! :read, @contact - end - - def edit - @contact = current_user_contacts.find(params[:id]) - end - - def update - @contact = current_user_contacts.find(params[:id]) - @contact.attributes = contact_params - response = update_contact_via_api(@contact.uuid) - updated = response.is_a?(Net::HTTPSuccess) - - if updated - redirect_to registrant_domain_contact_url(domain, @contact), notice: t('.updated') - else - parsed_response = JSON.parse(response.body, symbolize_names: true) - @errors = parsed_response[:errors] - render :edit - end - end - - private - - def set_contact - id = params[:id] - contact = domain.contacts.find_by(id: id) || current_user_contacts.find_by(id: id) - contact ||= Contact.find_by(id: id, ident: domain.registrant.ident) - @contact = contact - end - - def domain - current_user_domains.find(params[:domain_id]) - end - - def contact_params - permitted = %i[ - name - email - phone - ] - - permitted << :fax if fax_enabled? - permitted += %i[street zip city state country_code] if Contact.address_processing? - params.require(:contact).permit(*permitted) - end - - def access_token - uri = URI.parse("#{ENV['registrant_api_base_url']}/api/v1/registrant/auth/eid") - request = Net::HTTP::Post.new(uri) - request.form_data = access_token_request_params - - response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: (uri.scheme == 'https')) do |http| - http.request(request) - end - - json_doc = JSON.parse(response.body, symbolize_names: true) - json_doc[:access_token] - end - - def access_token_request_params - { ident: current_registrant_user.ident, - first_name: current_registrant_user.first_name, - last_name: current_registrant_user.last_name } - end - - def fax_enabled? - ENV['fax_enabled'] == 'true' - end - - def contact_update_api_params - params = contact_params - params = normalize_address_attributes_for_api(params) if Contact.address_processing? - params - end - - def normalize_address_attributes_for_api(params) - normalized = params - address_parts = {} - - Contact.address_attribute_names.each do |attr| - attr = attr.to_sym - address_parts[attr] = params[attr] - normalized.delete(attr) - end - - normalized[:address] = address_parts - normalized - end - - def update_contact_via_api(uuid) - uri = URI.parse("#{ENV['registrant_api_base_url']}/api/v1/registrant/contacts/#{uuid}") - request = Net::HTTP::Patch.new(uri) - request['Authorization'] = "Bearer #{access_token}" - request['Content-type'] = 'application/json' - request.body = contact_update_api_params.to_json - - Net::HTTP.start(uri.hostname, uri.port, use_ssl: (uri.scheme == 'https')) do |http| - http.request(request) - end - end - - def domain_filter_params - params.permit(:domain_filter) - end -end diff --git a/app/controllers/registrant/domain_delete_confirms_controller.rb b/app/controllers/registrant/domain_delete_confirms_controller.rb deleted file mode 100644 index 337ca2403..000000000 --- a/app/controllers/registrant/domain_delete_confirms_controller.rb +++ /dev/null @@ -1,44 +0,0 @@ -class Registrant::DomainDeleteConfirmsController < RegistrantController - skip_before_action :authenticate_registrant_user!, only: [:show, :update] - skip_authorization_check only: [:show, :update] - - def show - return if params[:confirmed] || params[:rejected] - - @domain = Domain.find(params[:id]) - @domain = nil unless @domain.registrant_delete_confirmable?(params[:token]) - end - - def update - @domain = Domain.find(params[:id]) - unless @domain.registrant_delete_confirmable?(params[:token]) - flash[:alert] = t(:registrant_domain_verification_failed) - return render 'show' - end - - @registrant_verification = RegistrantVerification.new(domain_id: @domain.id, - verification_token: params[:token]) - - initiator = current_registrant_user ? current_registrant_user.username : - t(:user_not_authenticated) - - confirmed = params[:confirmed] ? true : false - action = if confirmed - @registrant_verification.domain_registrant_delete_confirm!("email link #{initiator}") - else - @registrant_verification.domain_registrant_delete_reject!("email link #{initiator}") - end - - fail_msg = t("registrant_domain_delete_#{confirmed ? 'confirmed' : 'rejected'}_failed".to_sym) - success_msg = t("registrant_domain_verification_#{confirmed ? 'confirmed' : 'rejected'}".to_sym) - - flash[:alert] = action ? success_msg : fail_msg - (render 'show' && return) unless action - - if confirmed - redirect_to registrant_domain_delete_confirm_path(@domain.id, confirmed: true) - else - redirect_to registrant_domain_delete_confirm_path(@domain.id, rejected: true) - end - end -end diff --git a/app/controllers/registrant/domain_update_confirms_controller.rb b/app/controllers/registrant/domain_update_confirms_controller.rb deleted file mode 100644 index 0e4f2a582..000000000 --- a/app/controllers/registrant/domain_update_confirms_controller.rb +++ /dev/null @@ -1,44 +0,0 @@ -class Registrant::DomainUpdateConfirmsController < RegistrantController - skip_before_action :authenticate_registrant_user!, only: %i[show update] - skip_authorization_check only: %i[show update] - - def show - return if params[:confirmed] || params[:rejected] - @domain = Domain.find(params[:id]) - @domain = nil unless @domain.registrant_update_confirmable?(params[:token]) - end - - def update - @domain = Domain.find(params[:id]) - unless @domain.registrant_update_confirmable?(params[:token]) - flash[:alert] = t(:registrant_domain_verification_failed) - return render 'show' - end - - @registrant_verification = RegistrantVerification.new(domain_id: @domain.id, - verification_token: params[:token]) - - initiator = current_registrant_user ? current_registrant_user.username : - t(:user_not_authenticated) - - if params[:rejected] - if @registrant_verification.domain_registrant_change_reject!("email link, #{initiator}") - flash[:notice] = t(:registrant_domain_verification_rejected) - redirect_to registrant_domain_update_confirm_path(@domain.id, rejected: true) - else - flash[:alert] = t(:registrant_domain_verification_rejected_failed) - return render 'show' - end - elsif params[:confirmed] - if @registrant_verification.domain_registrant_change_confirm!("email link, #{initiator}") - Dispute.close_by_domain(@domain.name) if @domain.disputed? - - flash[:notice] = t(:registrant_domain_verification_confirmed) - redirect_to registrant_domain_update_confirm_path(@domain.id, confirmed: true) - else - flash[:alert] = t(:registrant_domain_verification_confirmed_failed) - return render 'show' - end - end - end -end diff --git a/app/controllers/registrant/domains_controller.rb b/app/controllers/registrant/domains_controller.rb deleted file mode 100644 index 216f87e54..000000000 --- a/app/controllers/registrant/domains_controller.rb +++ /dev/null @@ -1,79 +0,0 @@ -class Registrant::DomainsController < RegistrantController - def index - authorize! :view, :registrant_domains - - params[:q] ||= {} - normalize_search_parameters do - @q = current_user_domains.search(search_params) - end - - domains = @q.result - - respond_to do |format| - format.html do - @domains = domains.page(params[:page]) - domains_per_page = params[:results_per_page].to_i - @domains = @domains.per(domains_per_page) if domains_per_page.positive? - end - format.csv do - raw_csv = @q.result.to_csv - send_data raw_csv, filename: 'domains.csv', type: "#{Mime[:csv]}; charset=utf-8" - end - format.pdf do - view = ActionView::Base.new(ActionController::Base.view_paths, domains: domains) - raw_html = view.render(file: 'registrant/domains/list_pdf', layout: false) - raw_pdf = domains.pdf(raw_html) - - send_data raw_pdf, filename: 'domains.pdf' - end - end - end - - def show - @domain = current_user_domains.find(params[:id]) - authorize! :read, @domain - end - - def confirmation - authorize! :view, :registrant_domains - domain = current_user_domains.find(params[:id]) - - if (domain.statuses.include?(DomainStatus::PENDING_UPDATE) || - domain.statuses.include?(DomainStatus::PENDING_DELETE_CONFIRMATION)) && - domain.pending_json.present? - - @domain = domain - @confirmation_url = confirmation_url(domain) - else - flash[:warning] = I18n.t('available_verification_url_not_found') - redirect_to registrant_domain_path(domain) - end - end - - private - - 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 - - def confirmation_url(domain) - if domain.statuses.include?(DomainStatus::PENDING_UPDATE) - registrant_domain_update_confirm_url(token: domain.registrant_verification_token) - elsif domain.statuses.include?(DomainStatus::PENDING_DELETE_CONFIRMATION) - registrant_domain_delete_confirm_url(token: domain.registrant_verification_token) - end - end - - def search_params - params.require(:q).permit(:name_matches, :registrant_ident_eq, :valid_to_gteq, :valid_to_lteq, - :results_per_page) - end -end diff --git a/app/controllers/registrant/registrars_controller.rb b/app/controllers/registrant/registrars_controller.rb deleted file mode 100644 index 7bb101bb9..000000000 --- a/app/controllers/registrant/registrars_controller.rb +++ /dev/null @@ -1,6 +0,0 @@ -class Registrant::RegistrarsController < RegistrantController - def show - @registrar = Registrar.find(params[:id]) - authorize! :read, @registrar - end -end \ No newline at end of file diff --git a/app/controllers/registrant/sessions_controller.rb b/app/controllers/registrant/sessions_controller.rb deleted file mode 100644 index 73b6d52da..000000000 --- a/app/controllers/registrant/sessions_controller.rb +++ /dev/null @@ -1,17 +0,0 @@ -class Registrant::SessionsController < Devise::SessionsController - layout 'registrant/application' - - private - - def after_sign_in_path_for(_resource_or_scope) - registrant_root_path - end - - def after_sign_out_path_for(_resource_or_scope) - new_registrant_user_session_path - end - - def user_for_paper_trail - current_registrant_user.present? ? current_registrant_user.id_role_username : 'anonymous' - end -end diff --git a/app/controllers/registrar/admin_contacts_controller.rb b/app/controllers/registrar/admin_contacts_controller.rb new file mode 100644 index 000000000..a1400b6dc --- /dev/null +++ b/app/controllers/registrar/admin_contacts_controller.rb @@ -0,0 +1,18 @@ +class Registrar + class AdminContactsController < BulkChangeController + BASE_URL = URI.parse("#{ENV['repp_url']}domains/admin_contacts").freeze + ACTIVE_TAB = :admin_contact + + def update + authorize! :manage, :repp + uri = BASE_URL + request = form_request(uri) + response = do_request(request, uri) + start_notice = t('.replaced') + + process_response(response: response, + start_notice: start_notice, + active_tab: ACTIVE_TAB) + end + end +end diff --git a/app/controllers/registrar/base_controller.rb b/app/controllers/registrar/base_controller.rb index 54bed977b..2aad861b8 100644 --- a/app/controllers/registrar/base_controller.rb +++ b/app/controllers/registrar/base_controller.rb @@ -17,7 +17,7 @@ class Registrar private def check_ip_restriction - ip_restriction = Authorization::RestrictedIP.new(request.ip) + ip_restriction = Authorization::RestrictedIp.new(request.ip) allowed = ip_restriction.can_access_registrar_area?(current_registrar_user.registrar) return if allowed diff --git a/app/controllers/registrar/bulk_change_controller.rb b/app/controllers/registrar/bulk_change_controller.rb index 801ab0516..74bbf89e8 100644 --- a/app/controllers/registrar/bulk_change_controller.rb +++ b/app/controllers/registrar/bulk_change_controller.rb @@ -26,6 +26,84 @@ class Registrar private + def form_request(uri) + request = Net::HTTP::Patch.new(uri) + request.set_form_data(current_contact_id: params[:current_contact_id], + new_contact_id: params[:new_contact_id]) + request.basic_auth(current_registrar_user.username, + current_registrar_user.plain_text_password) + request + end + + def process_response(response:, start_notice: '', active_tab:) + parsed_response = JSON.parse(response.body, symbolize_names: true) + + if response.code == '200' + notices = success_notices(parsed_response, start_notice) + + flash[:notice] = notices.join(', ') + redirect_to registrar_domains_url + else + @error = response.code == '404' ? 'Contact(s) not found' : parsed_response[:message] + render file: 'registrar/bulk_change/new', locals: { active_tab: active_tab } + end + end + + def success_notices(parsed_response, start_notice) + notices = [start_notice] + + notices << "#{t('.affected_domains')}: " \ + "#{parsed_response[:data][:affected_domains].join(', ')}" + + if parsed_response[:data][:skipped_domains] + notices << "#{t('.skipped_domains')}: " \ + "#{parsed_response[:data][:skipped_domains].join(', ')}" + end + notices + end + + def do_request(request, uri) + response = if Rails.env.test? + do_test_request(request, uri) + elsif Rails.env.development? + do_dev_request(request, uri) + else + do_live_request(request, uri) + end + response + end + + def do_live_request(request, uri) + client_cert = File.read(ENV['cert_path']) + client_key = File.read(ENV['key_path']) + Net::HTTP.start(uri.hostname, uri.port, + use_ssl: (uri.scheme == 'https'), + cert: OpenSSL::X509::Certificate.new(client_cert), + key: OpenSSL::PKey::RSA.new(client_key)) do |http| + http.request(request) + end + end + + def do_dev_request(request, uri) + client_cert = File.read(ENV['cert_path']) + client_key = File.read(ENV['key_path']) + Net::HTTP.start(uri.hostname, uri.port, + use_ssl: (uri.scheme == 'https'), + verify_mode: OpenSSL::SSL::VERIFY_NONE, + cert: OpenSSL::X509::Certificate.new(client_cert), + key: OpenSSL::PKey::RSA.new(client_key)) do |http| + http.request(request) + end + end + + def do_test_request(request, uri) + Net::HTTP.start(uri.hostname, uri.port, + use_ssl: (uri.scheme == 'https'), + verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http| + http.request(request) + end + end + def ready_to_renew? domain_ids_for_bulk_renew.present? && params[:renew].present? end diff --git a/app/controllers/registrar/domain_transfers_controller.rb b/app/controllers/registrar/domain_transfers_controller.rb index 584a50d33..e055c38d8 100644 --- a/app/controllers/registrar/domain_transfers_controller.rb +++ b/app/controllers/registrar/domain_transfers_controller.rb @@ -25,32 +25,7 @@ class Registrar current_registrar_user.plain_text_password) - if Rails.env.test? - response = Net::HTTP.start(uri.hostname, uri.port, - use_ssl: (uri.scheme == 'https'), - verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http| - http.request(request) - end - elsif Rails.env.development? - client_cert = File.read(ENV['cert_path']) - client_key = File.read(ENV['key_path']) - response = Net::HTTP.start(uri.hostname, uri.port, - use_ssl: (uri.scheme == 'https'), - verify_mode: OpenSSL::SSL::VERIFY_NONE, - cert: OpenSSL::X509::Certificate.new(client_cert), - key: OpenSSL::PKey::RSA.new(client_key)) do |http| - http.request(request) - end - else - client_cert = File.read(ENV['cert_path']) - client_key = File.read(ENV['key_path']) - response = Net::HTTP.start(uri.hostname, uri.port, - use_ssl: (uri.scheme == 'https'), - cert: OpenSSL::X509::Certificate.new(client_cert), - key: OpenSSL::PKey::RSA.new(client_key)) do |http| - http.request(request) - end - end + response = do_request(request, uri) parsed_response = JSON.parse(response.body, symbolize_names: true) diff --git a/app/controllers/registrar/domains_controller.rb b/app/controllers/registrar/domains_controller.rb index 1a46da463..2e268af0b 100644 --- a/app/controllers/registrar/domains_controller.rb +++ b/app/controllers/registrar/domains_controller.rb @@ -49,7 +49,7 @@ class Registrar domain_presenters << ::DomainPresenter.new(domain: domain, view: view_context) end - raw_csv = Registrar::DomainListCSVPresenter.new(domains: domain_presenters, + 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" diff --git a/app/controllers/registrar/nameservers_controller.rb b/app/controllers/registrar/nameservers_controller.rb index 52c43bb1d..3eb23cd48 100644 --- a/app/controllers/registrar/nameservers_controller.rb +++ b/app/controllers/registrar/nameservers_controller.rb @@ -18,32 +18,7 @@ class Registrar request.basic_auth(current_registrar_user.username, current_registrar_user.plain_text_password) - if Rails.env.test? - response = Net::HTTP.start(uri.hostname, uri.port, - use_ssl: (uri.scheme == 'https'), - verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http| - http.request(request) - end - elsif Rails.env.development? - client_cert = File.read(ENV['cert_path']) - client_key = File.read(ENV['key_path']) - response = Net::HTTP.start(uri.hostname, uri.port, - use_ssl: (uri.scheme == 'https'), - verify_mode: OpenSSL::SSL::VERIFY_NONE, - cert: OpenSSL::X509::Certificate.new(client_cert), - key: OpenSSL::PKey::RSA.new(client_key)) do |http| - http.request(request) - end - else - client_cert = File.read(ENV['cert_path']) - client_key = File.read(ENV['key_path']) - response = Net::HTTP.start(uri.hostname, uri.port, - use_ssl: (uri.scheme == 'https'), - cert: OpenSSL::X509::Certificate.new(client_cert), - key: OpenSSL::PKey::RSA.new(client_key)) do |http| - http.request(request) - end - end + response = do_request(request, uri) parsed_response = JSON.parse(response.body, symbolize_names: true) diff --git a/app/controllers/registrar/sessions_controller.rb b/app/controllers/registrar/sessions_controller.rb index e413c4feb..ec7cda148 100644 --- a/app/controllers/registrar/sessions_controller.rb +++ b/app/controllers/registrar/sessions_controller.rb @@ -72,7 +72,7 @@ class Registrar end def check_ip_restriction - ip_restriction = Authorization::RestrictedIP.new(request.ip) + ip_restriction = Authorization::RestrictedIp.new(request.ip) allowed = ip_restriction.can_access_registrar_area_sign_in_page? return if allowed diff --git a/app/controllers/registrar/tech_contacts_controller.rb b/app/controllers/registrar/tech_contacts_controller.rb index 001651250..cc9238730 100644 --- a/app/controllers/registrar/tech_contacts_controller.rb +++ b/app/controllers/registrar/tech_contacts_controller.rb @@ -1,62 +1,19 @@ class Registrar class TechContactsController < BulkChangeController + BASE_URL = URI.parse("#{ENV['repp_url']}domains/contacts").freeze + ACTIVE_TAB = :technical_contact + def update authorize! :manage, :repp - uri = URI.parse("#{ENV['repp_url']}domains/contacts") + uri = BASE_URL + request = form_request(uri) + response = do_request(request, uri) + start_notice = t('.replaced') - request = Net::HTTP::Patch.new(uri) - request.set_form_data(current_contact_id: params[:current_contact_id], - new_contact_id: params[:new_contact_id]) - request.basic_auth(current_registrar_user.username, - current_registrar_user.plain_text_password) - - if Rails.env.test? - response = Net::HTTP.start(uri.hostname, uri.port, - use_ssl: (uri.scheme == 'https'), - verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http| - http.request(request) - end - elsif Rails.env.development? - client_cert = File.read(ENV['cert_path']) - client_key = File.read(ENV['key_path']) - response = Net::HTTP.start(uri.hostname, uri.port, - use_ssl: (uri.scheme == 'https'), - verify_mode: OpenSSL::SSL::VERIFY_NONE, - cert: OpenSSL::X509::Certificate.new(client_cert), - key: OpenSSL::PKey::RSA.new(client_key)) do |http| - http.request(request) - end - else - client_cert = File.read(ENV['cert_path']) - client_key = File.read(ENV['key_path']) - response = Net::HTTP.start(uri.hostname, uri.port, - use_ssl: (uri.scheme == 'https'), - cert: OpenSSL::X509::Certificate.new(client_cert), - key: OpenSSL::PKey::RSA.new(client_key)) do |http| - http.request(request) - end - end - - parsed_response = JSON.parse(response.body, symbolize_names: true) - - if response.code == '200' - notices = [t('.replaced')] - - notices << "#{t('.affected_domains')}: " \ - "#{parsed_response[:data][:affected_domains].join(', ')}" - - if parsed_response[:data][:skipped_domains] - notices << "#{t('.skipped_domains')}: " \ - "#{parsed_response[:data][:skipped_domains].join(', ')}" - end - - flash[:notice] = notices.join(', ') - redirect_to registrar_domains_url - else - @error = response.code == '404' ? 'Contact(s) not found' : parsed_response[:message] - render file: 'registrar/bulk_change/new', locals: { active_tab: :technical_contact } - end + process_response(response: response, + start_notice: start_notice, + active_tab: ACTIVE_TAB) end end end diff --git a/app/controllers/repp/v1/accounts_controller.rb b/app/controllers/repp/v1/accounts_controller.rb index 89c14808f..1e0fde466 100644 --- a/app/controllers/repp/v1/accounts_controller.rb +++ b/app/controllers/repp/v1/accounts_controller.rb @@ -4,8 +4,28 @@ module Repp def balance resp = { balance: current_user.registrar.cash_account.balance, currency: current_user.registrar.cash_account.currency } + resp[:transactions] = activities if params[:detailed] == 'true' render_success(data: resp) end + + def activities + arr = [] + registrar_activities.each do |a| + arr << { created_at: a.created_at, description: a.description, + type: a.activity_type == 'add_credit' ? 'credit' : 'debit', + sum: a.sum, balance: a.new_balance } + end + + arr + end + + def registrar_activities + activities = current_user.registrar.cash_account.activities.order(created_at: :desc) + activities = activities.where('created_at >= ?', params[:from]) if params[:from] + activities = activities.where('created_at <= ?', params[:until]) if params[:until] + + activities + end end end end diff --git a/app/controllers/repp/v1/domains/admin_contacts_controller.rb b/app/controllers/repp/v1/domains/admin_contacts_controller.rb new file mode 100644 index 000000000..2e9a285eb --- /dev/null +++ b/app/controllers/repp/v1/domains/admin_contacts_controller.rb @@ -0,0 +1,21 @@ +module Repp + module V1 + module Domains + class AdminContactsController < BaseContactsController + def update + super + + unless @new_contact.identical_to?(@current_contact) + @epp_errors << { code: 2304, msg: 'Admin contacts must be identical' } + end + + return handle_errors if @epp_errors.any? + + affected, skipped = AdminDomainContact.replace(@current_contact, @new_contact) + @response = { affected_domains: affected, skipped_domains: skipped } + render_success(data: @response) + end + end + end + end +end diff --git a/app/controllers/repp/v1/domains/base_contacts_controller.rb b/app/controllers/repp/v1/domains/base_contacts_controller.rb new file mode 100644 index 000000000..b601c5313 --- /dev/null +++ b/app/controllers/repp/v1/domains/base_contacts_controller.rb @@ -0,0 +1,31 @@ +module Repp + module V1 + module Domains + class BaseContactsController < BaseController + before_action :set_current_contact, only: [:update] + before_action :set_new_contact, only: [:update] + + def set_current_contact + @current_contact = current_user.registrar.contacts + .find_by!(code: contact_params[:current_contact_id]) + end + + def set_new_contact + @new_contact = current_user.registrar.contacts.find_by!(code: params[:new_contact_id]) + end + + def update + @epp_errors ||= [] + @epp_errors << { code: 2304, msg: 'New contact must be valid' } if @new_contact.invalid? + end + + private + + def contact_params + params.require(%i[current_contact_id new_contact_id]) + params.permit(:current_contact_id, :new_contact_id) + end + end + end + end +end diff --git a/app/controllers/repp/v1/domains/contacts_controller.rb b/app/controllers/repp/v1/domains/contacts_controller.rb index 75404e0c6..131615570 100644 --- a/app/controllers/repp/v1/domains/contacts_controller.rb +++ b/app/controllers/repp/v1/domains/contacts_controller.rb @@ -1,23 +1,9 @@ module Repp module V1 module Domains - class ContactsController < BaseController - before_action :set_current_contact, only: [:update] - before_action :set_new_contact, only: [:update] - - def set_current_contact - @current_contact = current_user.registrar.contacts.find_by!( - code: contact_params[:current_contact_id] - ) - end - - def set_new_contact - @new_contact = current_user.registrar.contacts.find_by!(code: params[:new_contact_id]) - end - + class ContactsController < BaseContactsController def update - @epp_errors ||= [] - @epp_errors << { code: 2304, msg: 'New contact must be valid' } if @new_contact.invalid? + super if @new_contact == @current_contact @epp_errors << { code: 2304, msg: 'New contact must be different from current' } @@ -29,13 +15,6 @@ module Repp @response = { affected_domains: affected, skipped_domains: skipped } render_success(data: @response) end - - private - - def contact_params - params.require(%i[current_contact_id new_contact_id]) - params.permit(:current_contact_id, :new_contact_id) - end end end end diff --git a/app/controllers/sso/tara_controller.rb b/app/controllers/sso/tara_controller.rb index 37c8ab608..eb046730b 100644 --- a/app/controllers/sso/tara_controller.rb +++ b/app/controllers/sso/tara_controller.rb @@ -14,7 +14,7 @@ module Sso # rubocop:disable Style/AndOr def callback(user, registrar: true) - session[:omniauth_hash] = user_hash + session[:omniauth_hash] = user_hash.delete_if { |key, _| key == 'credentials' } (show_error(registrar: registrar) and return) unless user flash[:notice] = t(:signed_in_successfully) diff --git a/app/interactions/domains/expired_pendings/process_clean.rb b/app/interactions/domains/expired_pendings/process_clean.rb index c6277c3c5..63a8f1ba5 100644 --- a/app/interactions/domains/expired_pendings/process_clean.rb +++ b/app/interactions/domains/expired_pendings/process_clean.rb @@ -17,7 +17,9 @@ module Domains def notify_pending_update RegistrantChangeMailer.expired(domain: domain, registrar: domain.registrar, - registrant: domain.registrant).deliver_later + registrant: domain.registrant, + send_to: [domain.new_registrant_email, + domain.registrant.email]).deliver_later end def notify_pending_delete diff --git a/app/jobs/registrant_change_expired_email_job.rb b/app/jobs/registrant_change_expired_email_job.rb deleted file mode 100644 index 3c1bc35e2..000000000 --- a/app/jobs/registrant_change_expired_email_job.rb +++ /dev/null @@ -1,20 +0,0 @@ -class RegistrantChangeExpiredEmailJob < Que::Job - def run(domain_id) - domain = Domain.find(domain_id) - log(domain) - RegistrantChangeMailer.expired(domain: domain, - registrar: domain.registrar, - registrant: domain.registrant).deliver_now - end - - private - - def log(domain) - message = "Send RegistrantChangeMailer#expired email for domain #{domain.name} (##{domain.id}) to #{domain.new_registrant_email}" - logger.info(message) - end - - def logger - Rails.logger - end -end diff --git a/app/lib/to_stdout.rb b/app/lib/to_stdout.rb new file mode 100644 index 000000000..eeab82c15 --- /dev/null +++ b/app/lib/to_stdout.rb @@ -0,0 +1,6 @@ +class ToStdout + def self.msg(message) + time = Time.zone.now.utc + STDOUT << "#{time} - #{message}\n" unless Rails.env.test? + end +end diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index af5d59d63..2fdb84366 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -6,10 +6,6 @@ class ApplicationMailer < ActionMailer::Base token = domain.registrant_verification_token base_url = ENV['registrant_portal_verifications_base_url'] - url = registrant_domain_delete_confirm_url(domain, token: token) if method == 'delete' - url ||= registrant_domain_update_confirm_url(domain, token: token) - return url if base_url.blank? - "#{base_url}/confirmation/#{domain.name_puny}/#{method}/#{token}" end end diff --git a/app/mailers/interceptors/punycode_interceptor.rb b/app/mailers/interceptors/punycode_interceptor.rb index 0680a7371..3bd38ebee 100644 --- a/app/mailers/interceptors/punycode_interceptor.rb +++ b/app/mailers/interceptors/punycode_interceptor.rb @@ -1,4 +1,4 @@ -class PunycodeInterceptor +class Interceptors::PunycodeInterceptor class << self def delivering_email(message) message.from = encode_addresses_as_punycode(message.from) @@ -21,4 +21,4 @@ class PunycodeInterceptor SimpleIDN.to_ascii(domain_part) end end -end \ No newline at end of file +end diff --git a/app/mailers/registrant_change_mailer.rb b/app/mailers/registrant_change_mailer.rb index 8f43f4ab5..101e6c3e1 100644 --- a/app/mailers/registrant_change_mailer.rb +++ b/app/mailers/registrant_change_mailer.rb @@ -38,13 +38,13 @@ class RegistrantChangeMailer < ApplicationMailer mail(to: domain.new_registrant_email, subject: subject) end - def expired(domain:, registrar:, registrant:) + def expired(domain:, registrar:, registrant:, send_to:) @domain = DomainPresenter.new(domain: domain, view: view_context) @registrar = RegistrarPresenter.new(registrar: registrar, view: view_context) @registrant = RegistrantPresenter.new(registrant: registrant, view: view_context) subject = default_i18n_subject(domain_name: domain.name) - mail(to: domain.new_registrant_email, subject: subject) + mail(to: send_to, subject: subject) end private diff --git a/app/models/ability.rb b/app/models/ability.rb index 0bee01f9c..66a8793bc 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -89,8 +89,8 @@ class Ability can :manage, BlockedDomain can :manage, ReservedDomain can :manage, DNS::Zone - can :manage, DomainVersion - can :manage, ContactVersion + can :manage, Version::DomainVersion + can :manage, Version::ContactVersion can :manage, Billing::Price can :manage, User can :manage, ApiUser diff --git a/app/models/account_activity.rb b/app/models/account_activity.rb index d8e6be4d4..9df64209a 100644 --- a/app/models/account_activity.rb +++ b/app/models/account_activity.rb @@ -13,6 +13,9 @@ class AccountActivity < ApplicationRecord def update_balance account.balance += sum account.save + + self.new_balance = account.balance + save end class << self diff --git a/app/models/action.rb b/app/models/action.rb index 273dee821..ac5ee7f72 100644 --- a/app/models/action.rb +++ b/app/models/action.rb @@ -1,5 +1,5 @@ class Action < ApplicationRecord - has_paper_trail versions: { class_name: 'ActionVersion' } + has_paper_trail versions: { class_name: 'Version::ActionVersion' } belongs_to :user belongs_to :contact diff --git a/app/models/actions/contact_delete.rb b/app/models/actions/contact_delete.rb index 59032d566..60d3252c4 100644 --- a/app/models/actions/contact_delete.rb +++ b/app/models/actions/contact_delete.rb @@ -19,6 +19,11 @@ module Actions return end + if contact.delete_prohibited? + contact.errors.add(:statuses, :delete_prohibited) + return + end + commit end diff --git a/app/models/admin_domain_contact.rb b/app/models/admin_domain_contact.rb index 14907403d..7ccf3efcb 100644 --- a/app/models/admin_domain_contact.rb +++ b/app/models/admin_domain_contact.rb @@ -1,2 +1,26 @@ class AdminDomainContact < DomainContact + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/MethodLength + def self.replace(current_contact, new_contact) + affected_domains = [] + skipped_domains = [] + admin_contacts = where(contact: current_contact) + + admin_contacts.each do |admin_contact| + if admin_contact.domain.bulk_update_prohibited? + skipped_domains << admin_contact.domain.name + next + end + begin + admin_contact.contact = new_contact + admin_contact.save! + affected_domains << admin_contact.domain.name + rescue ActiveRecord::RecordNotUnique + skipped_domains << admin_contact.domain.name + end + end + [affected_domains.sort, skipped_domains.sort] + end + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/MethodLength end diff --git a/app/models/authorization/restricted_ip.rb b/app/models/authorization/restricted_ip.rb index b3c7b7cdb..41bb15f98 100644 --- a/app/models/authorization/restricted_ip.rb +++ b/app/models/authorization/restricted_ip.rb @@ -1,5 +1,5 @@ module Authorization - class RestrictedIP + class RestrictedIp def initialize(ip) @ip = ip end diff --git a/app/models/billing/price.rb b/app/models/billing/price.rb index dac458b00..3b0c253d4 100644 --- a/app/models/billing/price.rb +++ b/app/models/billing/price.rb @@ -1,6 +1,6 @@ module Billing class Price < ApplicationRecord - include Concerns::Billing::Price::Expirable + include Billing::Price::Expirable include Versions belongs_to :zone, class_name: 'DNS::Zone', required: true diff --git a/app/models/bounced_mail_address.rb b/app/models/bounced_mail_address.rb index 73c6a0941..db4413829 100644 --- a/app/models/bounced_mail_address.rb +++ b/app/models/bounced_mail_address.rb @@ -1,5 +1,6 @@ class BouncedMailAddress < ApplicationRecord validates :email, :message_id, :bounce_type, :bounce_subtype, :action, :status, presence: true + after_destroy :destroy_aws_suppression def bounce_reason "#{action} (#{status} #{diagnostic})" @@ -25,4 +26,20 @@ class BouncedMailAddress < ApplicationRecord diagnostic: bounced_record['diagnosticCode'], } end + + def destroy_aws_suppression + return unless BouncedMailAddress.ses_configured? + + res = Aws::SESV2::Client.new.delete_suppressed_destination(email_address: email) + res.successful? + rescue Aws::SESV2::Errors::ServiceError => e + logger.warn("Suppression not removed. #{e}") + end + + def self.ses_configured? + ses ||= Aws::SESV2::Client.new + ses.config.credentials.access_key_id.present? + rescue Aws::Errors::MissingRegionError + false + end end diff --git a/app/models/concerns/billing/price/expirable.rb b/app/models/concerns/billing/price/expirable.rb index c0e05832a..2387bf320 100644 --- a/app/models/concerns/billing/price/expirable.rb +++ b/app/models/concerns/billing/price/expirable.rb @@ -1,4 +1,4 @@ -module Concerns::Billing::Price::Expirable +module Billing::Price::Expirable extend ActiveSupport::Concern class_methods do diff --git a/app/models/concerns/contact/archivable.rb b/app/models/concerns/contact/archivable.rb index 4526e04c5..ca2d19b1b 100644 --- a/app/models/concerns/contact/archivable.rb +++ b/app/models/concerns/contact/archivable.rb @@ -1,68 +1,64 @@ -module Concerns - module Contact - module Archivable - extend ActiveSupport::Concern +module Contact::Archivable + extend ActiveSupport::Concern - class_methods do - def archivable - unlinked.find_each.select(&:archivable?) - end - end - - def archivable?(post: false) - inactive = inactive? - - log("Found archivable contact id(#{id}), code (#{code})") if inactive && !post - - inactive - end - - def archive(verified: false, notify: true, extra_log: false) - unless verified - raise 'Contact cannot be archived' unless archivable?(post: true) - end - - notify_registrar_about_archivation if notify - write_to_registrar_log if extra_log - destroy! - end - - private - - def notify_registrar_about_archivation - registrar.notifications.create!( - text: I18n.t('contact_has_been_archived', - contact_code: code, orphan_months: Setting.orphans_contacts_in_months) - ) - end - - def inactive? - if DomainVersion.contact_unlinked_more_than?(contact_id: id, period: inactivity_period) - return true - end - - DomainVersion.was_contact_linked?(id) ? false : created_at <= inactivity_period.ago - end - - def inactivity_period - Setting.orphans_contacts_in_months.months - end - - def log(msg) - @log ||= Logger.new(STDOUT) - @log.info(msg) - end - - def write_to_registrar_log - registrar_name = registrar.accounting_customer_code - archive_path = ENV['contact_archivation_log_file_dir'] - registrar_log_path = "#{archive_path}/#{registrar_name}.txt" - FileUtils.mkdir_p(archive_path) unless Dir.exist?(archive_path) - - f = File.new(registrar_log_path, 'a+') - f.write("#{code}\n") - f.close - end + class_methods do + def archivable + unlinked.find_each.select(&:archivable?) end end + + def archivable?(post: false) + inactive = inactive? + + log("Found archivable contact id(#{id}), code (#{code})") if inactive && !post + + inactive + end + + def archive(verified: false, notify: true, extra_log: false) + unless verified + raise 'Contact cannot be archived' unless archivable?(post: true) + end + + notify_registrar_about_archivation if notify + write_to_registrar_log if extra_log + destroy! + end + + private + + def notify_registrar_about_archivation + registrar.notifications.create!( + text: I18n.t('contact_has_been_archived', + contact_code: code, orphan_months: Setting.orphans_contacts_in_months) + ) + end + + def inactive? + if Version::DomainVersion.contact_unlinked_more_than?(contact_id: id, period: inactivity_period) + return true + end + + Version::DomainVersion.was_contact_linked?(id) ? false : created_at <= inactivity_period.ago + end + + def inactivity_period + Setting.orphans_contacts_in_months.months + end + + def log(msg) + @log ||= Logger.new(STDOUT) + @log.info(msg) + end + + def write_to_registrar_log + registrar_name = registrar.accounting_customer_code + archive_path = ENV['contact_archivation_log_file_dir'] + registrar_log_path = "#{archive_path}/#{registrar_name}.txt" + FileUtils.mkdir_p(archive_path) unless Dir.exist?(archive_path) + + f = File.new(registrar_log_path, 'a+') + f.write("#{code}\n") + f.close + end end diff --git a/app/models/concerns/contact/disclosable.rb b/app/models/concerns/contact/disclosable.rb index 6c3b81849..a61b240b1 100644 --- a/app/models/concerns/contact/disclosable.rb +++ b/app/models/concerns/contact/disclosable.rb @@ -1,26 +1,22 @@ -module Concerns - module Contact - module Disclosable - extend ActiveSupport::Concern +module Contact::Disclosable + extend ActiveSupport::Concern - class_methods do - attr_accessor :disclosable_attributes - end + class_methods do + attr_accessor :disclosable_attributes + end - included do - self.disclosable_attributes = %w[name email] - validate :validate_disclosed_attributes - end + included do + self.disclosable_attributes = %w[name email] + validate :validate_disclosed_attributes + end - private + private - def validate_disclosed_attributes - return if disclosed_attributes.empty? + def validate_disclosed_attributes + return if disclosed_attributes.empty? - has_undisclosable_attributes = (disclosed_attributes - self.class.disclosable_attributes) - .any? - errors.add(:disclosed_attributes, :invalid) if has_undisclosable_attributes - end - end + has_undisclosable_attributes = (disclosed_attributes - self.class.disclosable_attributes) + .any? + errors.add(:disclosed_attributes, :invalid) if has_undisclosable_attributes end end diff --git a/app/models/concerns/contact/identical.rb b/app/models/concerns/contact/identical.rb index f529e09ac..d9bcf1046 100644 --- a/app/models/concerns/contact/identical.rb +++ b/app/models/concerns/contact/identical.rb @@ -1,4 +1,4 @@ -module Concerns::Contact::Identical +module Contact::Identical extend ActiveSupport::Concern IDENTIFIABLE_ATTRIBUTES = %w[ @@ -11,6 +11,13 @@ module Concerns::Contact::Identical ident_country_code org_name ] + + IDENTICAL_ATTRIBUTES = %w[ + ident + ident_type + ident_country_code + ].freeze + private_constant :IDENTIFIABLE_ATTRIBUTES def identical(registrar) @@ -20,6 +27,12 @@ module Concerns::Contact::Identical .where.not(id: id).take end + def identical_to?(contact) + IDENTICAL_ATTRIBUTES.all? do |attribute| + attributes[attribute] == contact.attributes[attribute] + end + end + private def identifiable_hash diff --git a/app/models/concerns/domain/activatable.rb b/app/models/concerns/domain/activatable.rb index 58ff822d9..ae1bd6f7b 100644 --- a/app/models/concerns/domain/activatable.rb +++ b/app/models/concerns/domain/activatable.rb @@ -1,4 +1,4 @@ -module Concerns::Domain::Activatable +module Domain::Activatable extend ActiveSupport::Concern def active? diff --git a/app/models/concerns/domain/bulk_updatable.rb b/app/models/concerns/domain/bulk_updatable.rb new file mode 100644 index 000000000..6a462e1af --- /dev/null +++ b/app/models/concerns/domain/bulk_updatable.rb @@ -0,0 +1,13 @@ +module Domain::BulkUpdatable + extend ActiveSupport::Concern + + def bulk_update_prohibited? + discarded? || statuses_blocks_update? + end + + def statuses_blocks_update? + prohibited_array = [DomainStatus::SERVER_UPDATE_PROHIBITED, + DomainStatus::CLIENT_UPDATE_PROHIBITED] + prohibited_array.any? { |block_status| statuses.include?(block_status) } + end +end diff --git a/app/models/concerns/domain/deletable.rb b/app/models/concerns/domain/deletable.rb index 81518c739..50c418feb 100644 --- a/app/models/concerns/domain/deletable.rb +++ b/app/models/concerns/domain/deletable.rb @@ -1,6 +1,12 @@ -module Concerns::Domain::Deletable +module Domain::Deletable extend ActiveSupport::Concern + DELETE_STATUSES = [ + DomainStatus::PENDING_DELETE_CONFIRMATION, + DomainStatus::PENDING_DELETE, + DomainStatus::FORCE_DELETE, + ].freeze + private def delete_later diff --git a/app/models/concerns/domain/discardable.rb b/app/models/concerns/domain/discardable.rb index 25547af0f..abb105d80 100644 --- a/app/models/concerns/domain/discardable.rb +++ b/app/models/concerns/domain/discardable.rb @@ -1,4 +1,4 @@ -module Concerns::Domain::Discardable +module Domain::Discardable extend ActiveSupport::Concern def keep diff --git a/app/models/concerns/domain/disputable.rb b/app/models/concerns/domain/disputable.rb index a05d7cea6..a70d8b7cf 100644 --- a/app/models/concerns/domain/disputable.rb +++ b/app/models/concerns/domain/disputable.rb @@ -1,44 +1,40 @@ # frozen_string_literal: true -module Concerns - module Domain - module Disputable - extend ActiveSupport::Concern +module Domain::Disputable + extend ActiveSupport::Concern - included do - validate :validate_disputed - end + included do + validate :validate_disputed + end - def mark_as_disputed - statuses.push(DomainStatus::DISPUTED) unless statuses.include?(DomainStatus::DISPUTED) - save - end + def mark_as_disputed + statuses.push(DomainStatus::DISPUTED) unless statuses.include?(DomainStatus::DISPUTED) + save + end - def unmark_as_disputed - statuses.delete_if { |status| status == DomainStatus::DISPUTED } - save - end + def unmark_as_disputed + statuses.delete_if { |status| status == DomainStatus::DISPUTED } + save + end - def in_disputed_list? - @in_disputed_list ||= Dispute.active.find_by(domain_name: name).present? - end + def in_disputed_list? + @in_disputed_list ||= Dispute.active.find_by(domain_name: name).present? + end - def disputed? - Dispute.active.where(domain_name: name).any? - end + def disputed? + Dispute.active.where(domain_name: name).any? + end - def validate_disputed - return if persisted? || !in_disputed_list? + def validate_disputed + return if persisted? || !in_disputed_list? - if reserved_pw.blank? - errors.add(:base, :required_parameter_missing_disputed) - return false - end - - return if Dispute.valid_auth?(name, reserved_pw) - - errors.add(:base, :invalid_auth_information_reserved) - end + if reserved_pw.blank? + errors.add(:base, :required_parameter_missing_disputed) + return false end + + return if Dispute.valid_auth?(name, reserved_pw) + + errors.add(:base, :invalid_auth_information_reserved) end end diff --git a/app/models/concerns/domain/expirable.rb b/app/models/concerns/domain/expirable.rb index f4e8b61f8..1710f9dcd 100644 --- a/app/models/concerns/domain/expirable.rb +++ b/app/models/concerns/domain/expirable.rb @@ -1,4 +1,4 @@ -module Concerns::Domain::Expirable +module Domain::Expirable extend ActiveSupport::Concern included do diff --git a/app/models/concerns/domain/force_delete.rb b/app/models/concerns/domain/force_delete.rb index 87e9a957b..ca13eb5d1 100644 --- a/app/models/concerns/domain/force_delete.rb +++ b/app/models/concerns/domain/force_delete.rb @@ -1,4 +1,4 @@ -module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength +module Domain::ForceDelete # rubocop:disable Metrics/ModuleLength extend ActiveSupport::Concern included do @@ -11,6 +11,11 @@ module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength lambda { where("(force_delete_data->>'contact_notification_sent_date') is null") } + + HOLD_STATUSES = [ + DomainStatus::SERVER_HOLD, + DomainStatus::CLIENT_HOLD, + ].freeze end class_methods do @@ -19,6 +24,10 @@ module Concerns::Domain::ForceDelete # rubocop:disable Metrics/ModuleLength end end + def hold_status? + HOLD_STATUSES.any? { |status| statuses.include? status } + end + def notification_template(explicit: nil) reason = explicit&.downcase return reason if %w[invalid_email invalid_phone].include?(reason) diff --git a/app/models/concerns/domain/registry_lockable.rb b/app/models/concerns/domain/registry_lockable.rb index 4a759296d..2e80b7dda 100644 --- a/app/models/concerns/domain/registry_lockable.rb +++ b/app/models/concerns/domain/registry_lockable.rb @@ -1,51 +1,59 @@ -module Concerns - module Domain - module RegistryLockable - extend ActiveSupport::Concern +module Domain::RegistryLockable + extend ActiveSupport::Concern - def apply_registry_lock - return unless registry_lockable? - return if locked_by_registrant? + def apply_registry_lock + return unless registry_lockable? + return if locked_by_registrant? - transaction do - statuses << DomainStatus::SERVER_UPDATE_PROHIBITED - statuses << DomainStatus::SERVER_DELETE_PROHIBITED - statuses << DomainStatus::SERVER_TRANSFER_PROHIBITED - self.locked_by_registrant_at = Time.zone.now + transaction do + statuses << DomainStatus::SERVER_UPDATE_PROHIBITED + statuses << DomainStatus::SERVER_DELETE_PROHIBITED + statuses << DomainStatus::SERVER_TRANSFER_PROHIBITED + self.locked_by_registrant_at = Time.zone.now + alert_registrar_lock_changes!(lock: true) - save! - end - end - - def registry_lockable? - (statuses & [DomainStatus::PENDING_DELETE_CONFIRMATION, - DomainStatus::PENDING_CREATE, DomainStatus::PENDING_UPDATE, - DomainStatus::PENDING_DELETE, DomainStatus::PENDING_RENEW, - DomainStatus::PENDING_TRANSFER, DomainStatus::FORCE_DELETE]).empty? - end - - def locked_by_registrant? - return false unless locked_by_registrant_at - - lock_statuses = [DomainStatus::SERVER_UPDATE_PROHIBITED, - DomainStatus::SERVER_DELETE_PROHIBITED, - DomainStatus::SERVER_TRANSFER_PROHIBITED] - - (statuses & lock_statuses).count == 3 - end - - def remove_registry_lock - return unless locked_by_registrant? - - transaction do - statuses.delete(DomainStatus::SERVER_UPDATE_PROHIBITED) - statuses.delete(DomainStatus::SERVER_DELETE_PROHIBITED) - statuses.delete(DomainStatus::SERVER_TRANSFER_PROHIBITED) - self.locked_by_registrant_at = nil - - save! - end - end + save! end end + + def registry_lockable? + (statuses & [DomainStatus::PENDING_DELETE_CONFIRMATION, + DomainStatus::PENDING_CREATE, DomainStatus::PENDING_UPDATE, + DomainStatus::PENDING_DELETE, DomainStatus::PENDING_RENEW, + DomainStatus::PENDING_TRANSFER, DomainStatus::FORCE_DELETE]).empty? + end + + def locked_by_registrant? + return false unless locked_by_registrant_at + + lock_statuses = [DomainStatus::SERVER_UPDATE_PROHIBITED, + DomainStatus::SERVER_DELETE_PROHIBITED, + DomainStatus::SERVER_TRANSFER_PROHIBITED] + + (statuses & lock_statuses).count == 3 + end + + def remove_registry_lock + return unless locked_by_registrant? + + transaction do + statuses.delete(DomainStatus::SERVER_UPDATE_PROHIBITED) + statuses.delete(DomainStatus::SERVER_DELETE_PROHIBITED) + statuses.delete(DomainStatus::SERVER_TRANSFER_PROHIBITED) + self.locked_by_registrant_at = nil + alert_registrar_lock_changes!(lock: false) + + save! + end + end + + def alert_registrar_lock_changes!(lock: true) + translation = lock ? 'locked' : 'unlocked' + registrar.notifications.create!( + text: I18n.t("notifications.texts.registrar_#{translation}", + domain_name: name), + attached_obj_id: name, + attached_obj_type: self.class.name + ) + end end diff --git a/app/models/concerns/domain/releasable.rb b/app/models/concerns/domain/releasable.rb index 4aa5faa58..81410329b 100644 --- a/app/models/concerns/domain/releasable.rb +++ b/app/models/concerns/domain/releasable.rb @@ -1,55 +1,53 @@ -module Concerns - module Domain - module Releasable - extend ActiveSupport::Concern +module Domain::Releasable + extend ActiveSupport::Concern - class_methods do - def release_domains - releasable_domains.each do |domain| - domain.release - yield domain if block_given? - end - end - - private - - def releasable_domains - if release_to_auction - where('(delete_date <= ? OR force_delete_date <= ?)' \ - ' AND ? != ALL(coalesce(statuses, array[]::varchar[]))', - Time.zone.today, - Time.zone.today, - DomainStatus::SERVER_DELETE_PROHIBITED) - else - where('(delete_date <= ? OR force_delete_date <= ?)' \ - ' AND ? != ALL(coalesce(statuses, array[]::varchar[])) AND' \ - ' ? != ALL(COALESCE(statuses, array[]::varchar[]))', - Time.zone.today, - Time.zone.today, - DomainStatus::SERVER_DELETE_PROHIBITED, - DomainStatus::DELETE_CANDIDATE) - end - end + class_methods do + def release_domains + releasable_domains.each do |domain| + domain.release + yield domain if block_given? end + end - included do - class_attribute :release_to_auction - self.release_to_auction = ENV['release_domains_to_auction'] == 'true' - end + private - def release - if release_to_auction - transaction do - domain_name.sell_at_auction if domain_name.auctionable? - destroy! - registrar.notifications.create!(text: "#{I18n.t(:domain_deleted)}: #{name}", - attached_obj_id: id, - attached_obj_type: self.class) - end - else - discard - end + def releasable_domains + if release_to_auction + where('(delete_date <= ? OR force_delete_date <= ?)' \ + ' AND ? != ALL(coalesce(statuses, array[]::varchar[]))', + Time.zone.today, + Time.zone.today, + DomainStatus::SERVER_DELETE_PROHIBITED) + else + where('(delete_date <= ? OR force_delete_date <= ?)' \ + ' AND ? != ALL(coalesce(statuses, array[]::varchar[])) AND' \ + ' ? != ALL(COALESCE(statuses, array[]::varchar[]))', + Time.zone.today, + Time.zone.today, + DomainStatus::SERVER_DELETE_PROHIBITED, + DomainStatus::DELETE_CANDIDATE) end end end + + included do + class_attribute :release_to_auction + self.release_to_auction = ENV['release_domains_to_auction'] == 'true' + end + + def release + if release_to_auction + ToStdout.msg 'Destroying domain' + destroy! + ToStdout.msg "Checking if domain_name is auctionable: #{domain_name.auctionable?}" + domain_name.sell_at_auction if domain_name.auctionable? + + ToStdout.msg 'Sending registrar notification' + registrar.notifications.create!(text: "#{I18n.t(:domain_deleted)}: #{name}", + attached_obj_id: id, + attached_obj_type: self.class) + else + discard + end + end end diff --git a/app/models/concerns/domain/transferable.rb b/app/models/concerns/domain/transferable.rb index 9de2fff83..d280f6d67 100644 --- a/app/models/concerns/domain/transferable.rb +++ b/app/models/concerns/domain/transferable.rb @@ -1,4 +1,4 @@ -module Concerns::Domain::Transferable +module Domain::Transferable extend ActiveSupport::Concern included do @@ -31,7 +31,9 @@ module Concerns::Domain::Transferable DomainStatus::PENDING_TRANSFER, DomainStatus::FORCE_DELETE, DomainStatus::SERVER_TRANSFER_PROHIBITED, - DomainStatus::CLIENT_TRANSFER_PROHIBITED + DomainStatus::CLIENT_TRANSFER_PROHIBITED, + DomainStatus::SERVER_UPDATE_PROHIBITED, + DomainStatus::CLIENT_UPDATE_PROHIBITED, ]).empty? end @@ -59,7 +61,7 @@ module Concerns::Domain::Transferable copied_ids = [] domain_contacts.each do |dc| contact = Contact.find(dc.contact_id) - next if copied_ids.include?(contact.id) || contact.registrar == new_registrar + next if copied_ids.include?(uniq_contact_hash(dc)) || contact.registrar == new_registrar if registrant_id_was == contact.id # registrant was copied previously, do not copy it again oc = OpenStruct.new(id: registrant_id) @@ -72,7 +74,11 @@ module Concerns::Domain::Transferable else dc.update(contact_id: oc.id) end - copied_ids << contact.id + copied_ids << uniq_contact_hash(dc) end end + + def uniq_contact_hash(contact) + Digest::SHA1.hexdigest(contact.contact_id.to_s + contact.type) + end end diff --git a/app/models/concerns/email_verifable.rb b/app/models/concerns/email_verifable.rb index d0bb6aecb..457555b44 100644 --- a/app/models/concerns/email_verifable.rb +++ b/app/models/concerns/email_verifable.rb @@ -1,95 +1,93 @@ -module Concerns - module EmailVerifable - extend ActiveSupport::Concern +module EmailVerifable + extend ActiveSupport::Concern - def email_verification - @email_verification ||= EmailAddressVerification.find_or_create_by(email: unicode_email, - domain: domain(email)) - end + def email_verification + @email_verification ||= EmailAddressVerification.find_or_create_by(email: unicode_email, + domain: domain(email)) + end - def billing_email_verification - return unless attribute_names.include?('billing_email') + def billing_email_verification + return unless attribute_names.include?('billing_email') - @billing_email_verification ||= EmailAddressVerification - .find_or_create_by(email: unicode_billing_email, - domain: domain(billing_email)) - end + @billing_email_verification ||= EmailAddressVerification + .find_or_create_by(email: unicode_billing_email, + domain: domain(billing_email)) + end - def email_verification_failed? - email_verification&.failed? - end - - class_methods do - def domain(email) - Mail::Address.new(email).domain&.downcase || 'not_found' - rescue Mail::Field::IncompleteParseError - 'not_found' - end - - def local(email) - Mail::Address.new(email).local&.downcase || email - rescue Mail::Field::IncompleteParseError - email - end - - def punycode_to_unicode(email) - return email if domain(email) == 'not_found' - - local = local(email) - domain = SimpleIDN.to_unicode(domain(email)) - "#{local}@#{domain}"&.downcase - end - - def unicode_to_punycode(email) - return email if domain(email) == 'not_found' - - local = local(email) - domain = SimpleIDN.to_ascii(domain(email)) - "#{local}@#{domain}"&.downcase - end - end - - def unicode_billing_email - self.class.punycode_to_unicode(billing_email) - end - - def unicode_email - self.class.punycode_to_unicode(email) - end + def email_verification_failed? + email_verification&.failed? + end + class_methods do def domain(email) - SimpleIDN.to_unicode(self.class.domain(email)) + Mail::Address.new(email).domain&.downcase || 'not_found' + rescue Mail::Field::IncompleteParseError + 'not_found' + end + + def local(email) + Mail::Address.new(email).local&.downcase || email + rescue Mail::Field::IncompleteParseError + email end def punycode_to_unicode(email) - self.class.punycode_to_unicode(email) + return email if domain(email) == 'not_found' + + local = local(email) + domain = SimpleIDN.to_unicode(domain(email)) + "#{local}@#{domain}"&.downcase end - def correct_email_format - return if email.blank? + def unicode_to_punycode(email) + return email if domain(email) == 'not_found' - result = email_verification.verify - process_result(result: result, field: :email) + local = local(email) + domain = SimpleIDN.to_ascii(domain(email)) + "#{local}@#{domain}"&.downcase end - - def correct_billing_email_format - return if email.blank? - - result = billing_email_verification.verify - process_result(result: result, field: :billing_email) - end - - # rubocop:disable Metrics/LineLength - def process_result(result:, field:) - case result[:errors].keys.first - when :smtp - errors.add(field, I18n.t('activerecord.errors.models.contact.attributes.email.email_smtp_check_error')) - when :mx - errors.add(field, I18n.t('activerecord.errors.models.contact.attributes.email.email_mx_check_error')) - when :regex - errors.add(field, I18n.t('activerecord.errors.models.contact.attributes.email.email_regex_check_error')) - end - end - # rubocop:enable Metrics/LineLength end + + def unicode_billing_email + self.class.punycode_to_unicode(billing_email) + end + + def unicode_email + self.class.punycode_to_unicode(email) + end + + def domain(email) + SimpleIDN.to_unicode(self.class.domain(email)) + end + + def punycode_to_unicode(email) + self.class.punycode_to_unicode(email) + end + + def correct_email_format + return if email.blank? + + result = email_verification.verify + process_result(result: result, field: :email) + end + + def correct_billing_email_format + return if email.blank? + + result = billing_email_verification.verify + process_result(result: result, field: :billing_email) + end + + # rubocop:disable Metrics/LineLength + def process_result(result:, field:) + case result[:errors].keys.first + when :smtp + errors.add(field, I18n.t('activerecord.errors.models.contact.attributes.email.email_smtp_check_error')) + when :mx + errors.add(field, I18n.t('activerecord.errors.models.contact.attributes.email.email_mx_check_error')) + when :regex + errors.add(field, I18n.t('activerecord.errors.models.contact.attributes.email.email_regex_check_error')) + end + end + # rubocop:enable Metrics/LineLength end diff --git a/app/models/concerns/invoice/book_keeping.rb b/app/models/concerns/invoice/book_keeping.rb index 82e6506c9..03998cc50 100644 --- a/app/models/concerns/invoice/book_keeping.rb +++ b/app/models/concerns/invoice/book_keeping.rb @@ -1,34 +1,30 @@ -module Concerns - module Invoice - module BookKeeping - extend ActiveSupport::Concern +module Invoice::BookKeeping + extend ActiveSupport::Concern - def as_directo_json - invoice = ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(self)) - invoice['customer'] = compose_directo_customer - invoice['issue_date'] = issue_date.strftime('%Y-%m-%d') - invoice['transaction_date'] = account_activity - .bank_transaction&.paid_at&.strftime('%Y-%m-%d') - invoice['language'] = buyer.language == 'en' ? 'ENG' : '' - invoice['invoice_lines'] = compose_directo_product + def as_directo_json + invoice = ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(self)) + invoice['customer'] = compose_directo_customer + invoice['issue_date'] = issue_date.strftime('%Y-%m-%d') + invoice['transaction_date'] = account_activity + .bank_transaction&.paid_at&.strftime('%Y-%m-%d') + invoice['language'] = buyer.language == 'en' ? 'ENG' : '' + invoice['invoice_lines'] = compose_directo_product - invoice - end + invoice + end - def compose_directo_product - [{ 'product_id': Setting.directo_receipt_product_name, 'description': order, - 'quantity': 1, 'price': ActionController::Base.helpers.number_with_precision( - subtotal, precision: 2, separator: '.' - ) }].as_json - end + def compose_directo_product + [{ 'product_id': Setting.directo_receipt_product_name, 'description': order, + 'quantity': 1, 'price': ActionController::Base.helpers.number_with_precision( + subtotal, precision: 2, separator: '.' + ) }].as_json + end - def compose_directo_customer - { - 'code': buyer.accounting_customer_code, - 'destination': buyer_country_code, - 'vat_reg_no': buyer_vat_no, - }.as_json - end - end + def compose_directo_customer + { + 'code': buyer.accounting_customer_code, + 'destination': buyer_country_code, + 'vat_reg_no': buyer_vat_no, + }.as_json end end diff --git a/app/models/concerns/invoice/cancellable.rb b/app/models/concerns/invoice/cancellable.rb index 2eb0f8e2e..0374c9d2a 100644 --- a/app/models/concerns/invoice/cancellable.rb +++ b/app/models/concerns/invoice/cancellable.rb @@ -1,28 +1,24 @@ -module Concerns - module Invoice - module Cancellable - extend ActiveSupport::Concern +module Invoice::Cancellable + extend ActiveSupport::Concern - included do - scope :non_cancelled, -> { where(cancelled_at: nil) } - end + included do + scope :non_cancelled, -> { where(cancelled_at: nil) } + end - def cancellable? - unpaid? && not_cancelled? - end + def cancellable? + unpaid? && not_cancelled? + end - def cancel - raise 'Invoice cannot be cancelled' unless cancellable? - update!(cancelled_at: Time.zone.now) - end + def cancel + raise 'Invoice cannot be cancelled' unless cancellable? + update!(cancelled_at: Time.zone.now) + end - def cancelled? - cancelled_at - end + def cancelled? + cancelled_at + end - def not_cancelled? - !cancelled? - end - end + def not_cancelled? + !cancelled? end end diff --git a/app/models/concerns/invoice/payable.rb b/app/models/concerns/invoice/payable.rb index 1a1c3e269..ad91b886e 100644 --- a/app/models/concerns/invoice/payable.rb +++ b/app/models/concerns/invoice/payable.rb @@ -1,28 +1,24 @@ -module Concerns - module Invoice - module Payable - extend ActiveSupport::Concern +module Invoice::Payable + extend ActiveSupport::Concern - included do - scope :unpaid, -> { where('id NOT IN (SELECT invoice_id FROM account_activities WHERE' \ - ' invoice_id IS NOT NULL)') } - end + included do + scope :unpaid, -> { where('id NOT IN (SELECT invoice_id FROM account_activities WHERE' \ + ' invoice_id IS NOT NULL)') } + end - def payable? - unpaid? && not_cancelled? - end + def payable? + unpaid? && not_cancelled? + end - def paid? - account_activity - end + def paid? + account_activity + end - def receipt_date - account_activity.created_at.to_date - end + def receipt_date + account_activity.created_at.to_date + end - def unpaid? - !paid? - end - end + def unpaid? + !paid? end end diff --git a/app/models/concerns/registrar/book_keeping.rb b/app/models/concerns/registrar/book_keeping.rb index 60b9c2b1a..d8a7c2e72 100644 --- a/app/models/concerns/registrar/book_keeping.rb +++ b/app/models/concerns/registrar/book_keeping.rb @@ -1,128 +1,124 @@ -module Concerns - module Registrar - module BookKeeping - extend ActiveSupport::Concern +module Registrar::BookKeeping + extend ActiveSupport::Concern - DOMAIN_TO_PRODUCT = { 'ee': '01EE', 'com.ee': '02COM', 'pri.ee': '03PRI', - 'fie.ee': '04FIE', 'med.ee': '05MED' }.freeze + DOMAIN_TO_PRODUCT = { 'ee': '01EE', 'com.ee': '02COM', 'pri.ee': '03PRI', + 'fie.ee': '04FIE', 'med.ee': '05MED' }.freeze - def monthly_summary(month:) - activities = monthly_activites(month) - return unless activities.any? + def monthly_summary(month:) + activities = monthly_activites(month) + return unless activities.any? - invoice = { - 'number': 1, - 'customer': compose_directo_customer, - 'language': language == 'en' ? 'ENG' : '', 'currency': activities.first.currency, - 'date': month.end_of_month.strftime('%Y-%m-%d') - }.as_json + invoice = { + 'number': 1, + 'customer': compose_directo_customer, + 'language': language == 'en' ? 'ENG' : '', 'currency': activities.first.currency, + 'date': month.end_of_month.strftime('%Y-%m-%d') + }.as_json - invoice['invoice_lines'] = prepare_invoice_lines(month: month, activities: activities) + invoice['invoice_lines'] = prepare_invoice_lines(month: month, activities: activities) - invoice - end + invoice + end - def prepare_invoice_lines(month:, activities:) - lines = [] + def prepare_invoice_lines(month:, activities:) + lines = [] - lines << { 'description': title_for_summary(month) } - activities.each do |activity| - fetch_invoice_lines(activity, lines) - end - lines << prepayment_for_all(lines) + lines << { 'description': title_for_summary(month) } + activities.each do |activity| + fetch_invoice_lines(activity, lines) + end + lines << prepayment_for_all(lines) - lines.as_json - end + lines.as_json + end - def title_for_summary(date) - I18n.with_locale(language == 'en' ? 'en' : 'et') do - I18n.t('registrar.monthly_summary_title', date: I18n.l(date, format: '%B %Y')) - end - end - - def fetch_invoice_lines(activity, lines) - price = load_price(activity) - if price.duration.include? 'year' - price.duration.to_i.times do |duration| - lines << new_monthly_invoice_line(activity: activity, duration: duration + 1).as_json - end - else - lines << new_monthly_invoice_line(activity: activity).as_json - end - end - - def monthly_activites(month) - AccountActivity.where(account_id: account_ids) - .where(created_at: month.beginning_of_month..month.end_of_month) - .where(activity_type: [AccountActivity::CREATE, AccountActivity::RENEW]) - end - - def new_monthly_invoice_line(activity:, duration: nil) - price = load_price(activity) - line = { - 'product_id': DOMAIN_TO_PRODUCT[price.zone_name.to_sym], - 'quantity': 1, - 'unit': language == 'en' ? 'pc' : 'tk', - } - - finalize_invoice_line(line, price: price, duration: duration, activity: activity) - end - - def finalize_invoice_line(line, price:, activity:, duration:) - yearly = price.duration.include?('year') - - line['price'] = yearly ? (price.price.amount / price.duration.to_i) : price.price.amount - line['description'] = description_in_language(price: price, yearly: yearly) - - if duration.present? - add_product_timeframe(line: line, activity: activity, duration: duration) if duration > 1 - end - - line - end - - def add_product_timeframe(line:, activity:, duration:) - create_time = activity.created_at - line['start_date'] = (create_time + (duration - 1).year).end_of_month.strftime('%Y-%m-%d') - line['end_date'] = (create_time + (duration - 1).year + 1).end_of_month.strftime('%Y-%m-%d') - end - - def description_in_language(price:, yearly:) - timeframe_string = yearly ? 'yearly' : 'monthly' - locale_string = "registrar.invoice_#{timeframe_string}_product_description" - - I18n.with_locale(language == 'en' ? 'en' : 'et') do - I18n.t(locale_string, tld: ".#{price.zone_name}", length: price.duration.to_i) - end - end - - def prepayment_for_all(lines) - total = 0 - en = language == 'en' - lines.each { |l| total += l['quantity'].to_f * l['price'].to_f } - { - 'product_id': Setting.directo_receipt_product_name, - 'description': en ? 'Domains prepayment' : 'Domeenide ettemaks', - 'quantity': -1, - 'price': total, - 'unit': en ? 'pc' : 'tk', - } - end - - def compose_directo_customer - { - 'code': accounting_customer_code, - 'destination': address_country_code, - 'vat_reg_no': vat_no, - }.as_json - end - - def load_price(account_activity) - @pricelists ||= {} - return @pricelists[account_activity.price_id] if @pricelists.key? account_activity.price_id - - @pricelists[account_activity.price_id] = account_activity.price - end + def title_for_summary(date) + I18n.with_locale(language == 'en' ? 'en' : 'et') do + I18n.t('registrar.monthly_summary_title', date: I18n.l(date, format: '%B %Y')) end end + + def fetch_invoice_lines(activity, lines) + price = load_price(activity) + if price.duration.include? 'year' + price.duration.to_i.times do |duration| + lines << new_monthly_invoice_line(activity: activity, duration: duration + 1).as_json + end + else + lines << new_monthly_invoice_line(activity: activity).as_json + end + end + + def monthly_activites(month) + AccountActivity.where(account_id: account_ids) + .where(created_at: month.beginning_of_month..month.end_of_month) + .where(activity_type: [AccountActivity::CREATE, AccountActivity::RENEW]) + end + + def new_monthly_invoice_line(activity:, duration: nil) + price = load_price(activity) + line = { + 'product_id': DOMAIN_TO_PRODUCT[price.zone_name.to_sym], + 'quantity': 1, + 'unit': language == 'en' ? 'pc' : 'tk', + } + + finalize_invoice_line(line, price: price, duration: duration, activity: activity) + end + + def finalize_invoice_line(line, price:, activity:, duration:) + yearly = price.duration.include?('year') + + line['price'] = yearly ? (price.price.amount / price.duration.to_i) : price.price.amount + line['description'] = description_in_language(price: price, yearly: yearly) + + if duration.present? + add_product_timeframe(line: line, activity: activity, duration: duration) if duration > 1 + end + + line + end + + def add_product_timeframe(line:, activity:, duration:) + create_time = activity.created_at + line['start_date'] = (create_time + (duration - 1).year).end_of_month.strftime('%Y-%m-%d') + line['end_date'] = (create_time + (duration - 1).year + 1).end_of_month.strftime('%Y-%m-%d') + end + + def description_in_language(price:, yearly:) + timeframe_string = yearly ? 'yearly' : 'monthly' + locale_string = "registrar.invoice_#{timeframe_string}_product_description" + + I18n.with_locale(language == 'en' ? 'en' : 'et') do + I18n.t(locale_string, tld: ".#{price.zone_name}", length: price.duration.to_i) + end + end + + def prepayment_for_all(lines) + total = 0 + en = language == 'en' + lines.each { |l| total += l['quantity'].to_f * l['price'].to_f } + { + 'product_id': Setting.directo_receipt_product_name, + 'description': en ? 'Domains prepayment' : 'Domeenide ettemaks', + 'quantity': -1, + 'price': total, + 'unit': en ? 'pc' : 'tk', + } + end + + def compose_directo_customer + { + 'code': accounting_customer_code, + 'destination': address_country_code, + 'vat_reg_no': vat_no, + }.as_json + end + + def load_price(account_activity) + @pricelists ||= {} + return @pricelists[account_activity.price_id] if @pricelists.key? account_activity.price_id + + @pricelists[account_activity.price_id] = account_activity.price + end end diff --git a/app/models/concerns/registrar/legal_doc.rb b/app/models/concerns/registrar/legal_doc.rb index 2f21f6637..294c9487d 100644 --- a/app/models/concerns/registrar/legal_doc.rb +++ b/app/models/concerns/registrar/legal_doc.rb @@ -1,16 +1,12 @@ -module Concerns - module Registrar - module LegalDoc - extend ActiveSupport::Concern +module Registrar::LegalDoc + extend ActiveSupport::Concern - def legaldoc_mandatory? - !legaldoc_not_mandatory? - end + def legaldoc_mandatory? + !legaldoc_not_mandatory? + end - def legaldoc_not_mandatory? - setting = Setting.legal_document_is_mandatory - legaldoc_optout || !setting - end - end + def legaldoc_not_mandatory? + setting = Setting.legal_document_is_mandatory + legaldoc_optout || !setting end end diff --git a/app/models/concerns/versions.rb b/app/models/concerns/versions.rb index 033ebe52a..a1c872b56 100644 --- a/app/models/concerns/versions.rb +++ b/app/models/concerns/versions.rb @@ -7,10 +7,10 @@ module Versions attr_accessor :version_loader if WITH_CHILDREN.include?(model_name.name) - has_paper_trail versions: { class_name: "#{model_name}Version" }, + has_paper_trail versions: { class_name: "Version::#{model_name}Version" }, meta: { children: :children_log } else - has_paper_trail versions: { class_name: "#{model_name}Version" } + has_paper_trail versions: { class_name: "Version::#{model_name}Version" } end # add creator and updator diff --git a/app/models/concerns/zone/whois_queryable.rb b/app/models/concerns/zone/whois_queryable.rb index c79700582..e4a6c1314 100644 --- a/app/models/concerns/zone/whois_queryable.rb +++ b/app/models/concerns/zone/whois_queryable.rb @@ -1,74 +1,70 @@ -module Concerns - module Zone - module WhoisQueryable - extend ActiveSupport::Concern +module Zone::WhoisQueryable + extend ActiveSupport::Concern - included do - after_save :update_whois_record, if: :subzone? - after_destroy :update_whois_record - end + included do + after_save :update_whois_record, if: :subzone? + after_destroy :update_whois_record + end - def subzone? - origin.include? '.' - end + def subzone? + origin.include? '.' + end - def update_whois_record - UpdateWhoisRecordJob.enqueue origin, 'zone' - end + def update_whois_record + UpdateWhoisRecordJob.enqueue origin, 'zone' + end - def generate_data - wr = Whois::Record.find_or_initialize_by(name: origin) - wr.json = generate_json - wr.save - end + def generate_data + wr = Whois::Record.find_or_initialize_by(name: origin) + wr.json = generate_json + wr.save + end - def generate_json - data = {}.with_indifferent_access - [domain_vars, registrar_vars, registrant_vars].each do |h| - data.merge!(h) - end - - data - end - - # Take note - since this concern only used to zone whois queries, dnssec keys are set to - # empty array - def domain_vars - { disclaimer: Setting.registry_whois_disclaimer, name: origin, - registered: created_at.try(:to_s, :iso8601), status: ['ok (paid and in zone)'], - changed: updated_at.try(:to_s, :iso8601), email: Setting.registry_email, - admin_contacts: [contact_vars], tech_contacts: [contact_vars], - nameservers: nameserver_vars, dnssec_keys: [], dnssec_changed: nil } - end - - def registrar_vars - { registrar: Setting.registry_juridical_name, registrar_website: Setting.registry_url, - registrar_phone: Setting.registry_phone } - end - - def registrant_vars - { registrant: Setting.registry_juridical_name, registrant_reg_no: Setting.registry_reg_no, - registrant_ident_country_code: Setting.registry_country_code, registrant_kind: 'org', - registrant_disclosed_attributes: %w[name email] } - end - - def contact_vars - { name: Setting.registry_invoice_contact, email: Setting.registry_email, - disclosed_attributes: %w[name email] } - end - - def nameserver_vars - vars = [] - return vars unless ns_records - - parsed_ns = ns_records.gsub("\r", '').gsub("\n", '') - parsed_ns.split("#{origin}. IN NS ").each do |ns| - ns.delete_suffix! '.' - vars << ns if ns.match? Nameserver::HOSTNAME_REGEXP - end - - vars - end + def generate_json + data = {}.with_indifferent_access + [domain_vars, registrar_vars, registrant_vars].each do |h| + data.merge!(h) end + + data + end + + # Take note - since this concern only used to zone whois queries, dnssec keys are set to + # empty array + def domain_vars + { disclaimer: Setting.registry_whois_disclaimer, name: origin, + registered: created_at.try(:to_s, :iso8601), status: ['ok (paid and in zone)'], + changed: updated_at.try(:to_s, :iso8601), email: Setting.registry_email, + admin_contacts: [contact_vars], tech_contacts: [contact_vars], + nameservers: nameserver_vars, dnssec_keys: [], dnssec_changed: nil } + end + + def registrar_vars + { registrar: Setting.registry_juridical_name, registrar_website: Setting.registry_url, + registrar_phone: Setting.registry_phone } + end + + def registrant_vars + { registrant: Setting.registry_juridical_name, registrant_reg_no: Setting.registry_reg_no, + registrant_ident_country_code: Setting.registry_country_code, registrant_kind: 'org', + registrant_disclosed_attributes: %w[name email] } + end + + def contact_vars + { name: Setting.registry_invoice_contact, email: Setting.registry_email, + disclosed_attributes: %w[name email] } + end + + def nameserver_vars + vars = [] + return vars unless ns_records + + parsed_ns = ns_records.gsub("\r", '').gsub("\n", '') + parsed_ns.split("#{origin}. IN NS ").each do |ns| + ns.delete_suffix! '.' + vars << ns if ns.match? Nameserver::HOSTNAME_REGEXP + end + + vars end end diff --git a/app/models/contact.rb b/app/models/contact.rb index e30312b4a..61d49c10c 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -4,11 +4,11 @@ class Contact < ApplicationRecord include Versions # version/contact_version.rb include EppErrors include UserEvents - include Concerns::Contact::Transferable - include Concerns::Contact::Identical - include Concerns::Contact::Disclosable - include Concerns::Contact::Archivable - include Concerns::EmailVerifable + include Contact::Transferable + include Contact::Identical + include Contact::Disclosable + include Contact::Archivable + include EmailVerifable belongs_to :original, class_name: self.name belongs_to :registrar, required: true @@ -360,9 +360,11 @@ class Contact < ApplicationRecord @desc end + # Limits returned objects to 11 def related_domains - a = related_domain_descriptions - a.keys.map { |d| { name: d, id: a[d][:id], roles: a[d][:roles] } } + ids = DomainContact.select(:domain_id).where(contact_id: id).limit(11).map(&:domain_id).uniq + res = Domain.where(id: ids).or(Domain.where(registrant_id: id)).select(:name, :uuid).limit(11) + res.pluck(:name, :uuid).map { |name, id| { name: name, id: id } } end def status_notes_array=(notes) diff --git a/app/models/concerns/contact/transferable.rb b/app/models/contact/transferable.rb similarity index 91% rename from app/models/concerns/contact/transferable.rb rename to app/models/contact/transferable.rb index 987933a8d..b10a3acfc 100644 --- a/app/models/concerns/contact/transferable.rb +++ b/app/models/contact/transferable.rb @@ -1,4 +1,4 @@ -module Concerns::Contact::Transferable +module Contact::Transferable extend ActiveSupport::Concern included do @@ -9,7 +9,7 @@ module Concerns::Contact::Transferable def transfer(new_registrar) return identical(new_registrar) if identical(new_registrar) - new_contact = self.dup + new_contact = dup new_contact.registrar = new_registrar new_contact.original = self new_contact.code = nil diff --git a/app/models/contact_request.rb b/app/models/contact_request.rb new file mode 100644 index 000000000..f4c6db716 --- /dev/null +++ b/app/models/contact_request.rb @@ -0,0 +1,41 @@ +class ContactRequest < ApplicationRecord + establish_connection :"whois_#{Rails.env}" + self.table_name = 'contact_requests' + + STATUS_NEW = 'new'.freeze + STATUS_CONFIRMED = 'confirmed'.freeze + STATUS_SENT = 'sent'.freeze + STATUSES = [STATUS_NEW, STATUS_CONFIRMED, STATUS_SENT].freeze + + validates :whois_record_id, presence: true + validates :email, presence: true + validates :name, presence: true + validates :status, inclusion: { in: STATUSES } + + attr_readonly :secret, + :valid_to + + def self.save_record(params) + contact_request = new(params) + contact_request.secret = create_random_secret + contact_request.valid_to = set_valid_to_24_hours_from_now + contact_request.status = STATUS_NEW + contact_request.save! + contact_request + end + + def update_record(params) + self.status = params['status'] if params['status'] + self.ip_address = params['ip'] if params['ip'] + self.message_id = params['ip'] if params['message_id'] + save! + end + + def self.create_random_secret + SecureRandom.hex(64) + end + + def self.set_valid_to_24_hours_from_now + (Time.zone.now + 24.hours) + end +end diff --git a/app/models/dns/domain_name.rb b/app/models/dns/domain_name.rb index c1af4d5e7..1e9cd6587 100644 --- a/app/models/dns/domain_name.rb +++ b/app/models/dns/domain_name.rb @@ -36,6 +36,7 @@ module DNS auction = Auction.new auction.domain = name auction.start + ToStdout.msg "Created the auction: #{auction.inspect}" update_whois_from_auction(auction) end @@ -100,7 +101,8 @@ module DNS whois_record = Whois::Record.find_or_create_by!(name: name) do |record| record.json = {} end - + ToStdout.msg "Starting to update WHOIS record #{whois_record.inspect}\n\n"\ + "from auction #{auction.inspect}" whois_record.update_from_auction(auction) end end diff --git a/app/models/dns/zone.rb b/app/models/dns/zone.rb index 31749d952..6e18b84bb 100644 --- a/app/models/dns/zone.rb +++ b/app/models/dns/zone.rb @@ -5,7 +5,7 @@ module DNS validates :origin, :ttl, :refresh, :retry, :expire, :minimum_ttl, :email, :master_nameserver, presence: true validates :ttl, :refresh, :retry, :expire, :minimum_ttl, numericality: { only_integer: true } validates :origin, uniqueness: true - include Concerns::Zone::WhoisQueryable + include ::Zone::WhoisQueryable before_destroy do throw(:abort) if used? diff --git a/app/models/domain.rb b/app/models/domain.rb index 88fa94fbc..657688016 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -1,15 +1,16 @@ class Domain < ApplicationRecord include UserEvents include Versions # version/domain_version.rb - include Concerns::Domain::Expirable - include Concerns::Domain::Activatable - include Concerns::Domain::ForceDelete - include Concerns::Domain::Discardable - include Concerns::Domain::Deletable - include Concerns::Domain::Transferable - include Concerns::Domain::RegistryLockable - include Concerns::Domain::Releasable - include Concerns::Domain::Disputable + include Domain::Expirable + include Domain::Activatable + include Domain::ForceDelete + include Domain::Discardable + include Domain::Deletable + include Domain::Transferable + include Domain::RegistryLockable + include Domain::Releasable + include Domain::Disputable + include Domain::BulkUpdatable attr_accessor :roles @@ -78,7 +79,7 @@ class Domain < ApplicationRecord true end - after_commit :update_whois_record, unless: -> { domain_name.at_auction? } + after_commit :update_whois_record after_create :update_reserved_domains def update_reserved_domains @@ -106,13 +107,13 @@ class Domain < ApplicationRecord validate :status_is_consistant def status_is_consistant - has_error = (statuses.include?(DomainStatus::SERVER_HOLD) && statuses.include?(DomainStatus::SERVER_MANUAL_INZONE)) - unless has_error - if (statuses & [DomainStatus::PENDING_DELETE_CONFIRMATION, DomainStatus::PENDING_DELETE, DomainStatus::FORCE_DELETE]).any? - has_error = statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED - end + has_error = (hold_status? && statuses.include?(DomainStatus::SERVER_MANUAL_INZONE)) + unless has_error + if (statuses & DELETE_STATUSES).any? + has_error = statuses.include? DomainStatus::SERVER_DELETE_PROHIBITED end - errors.add(:domains, I18n.t(:object_status_prohibits_operation)) if has_error + end + errors.add(:domains, I18n.t(:object_status_prohibits_operation)) if has_error end attr_accessor :is_admin @@ -197,6 +198,23 @@ class Domain < ApplicationRecord Setting.nameserver_required end + def registrant_user_admin_registrant_domains(registrant_user) + companies = Contact.registrant_user_company_contacts(registrant_user) + from( + "(#{registrant_user_administered_domains(registrant_user).to_sql} UNION " \ + "#{registrant_user_company_registrant(companies).to_sql} UNION " \ + "#{registrant_user_domains_company(companies, except_tech: true).to_sql}) AS domains" + ) + end + + def registrant_user_direct_admin_registrant_domains(registrant_user) + from( + "(#{registrant_user_direct_domains_by_registrant(registrant_user).to_sql} UNION " \ + "#{registrant_user_direct_domains_by_contact(registrant_user, + except_tech: true).to_sql}) AS domains" + ) + end + def registrant_user_domains(registrant_user) from( "(#{registrant_user_domains_by_registrant(registrant_user).to_sql} UNION " \ @@ -246,16 +264,20 @@ class Domain < ApplicationRecord where(registrant: registrant_user.direct_contacts) end - def registrant_user_direct_domains_by_contact(registrant_user) - joins(:domain_contacts).where(domain_contacts: { contact_id: registrant_user.direct_contacts }) + def registrant_user_direct_domains_by_contact(registrant_user, except_tech: false) + request = { contact_id: registrant_user.direct_contacts } + request[:type] = [AdminDomainContact.name] if except_tech + joins(:domain_contacts).where(domain_contacts: request) end def registrant_user_company_registrant(companies) where(registrant: companies) end - def registrant_user_domains_company(companies) - joins(:domain_contacts).where(domain_contacts: { contact: companies }) + def registrant_user_domains_company(companies, except_tech: false) + request = { contact: companies } + request[:type] = [AdminDomainContact.name] if except_tech + joins(:domain_contacts).where(domain_contacts: request) end end diff --git a/app/models/domain_status.rb b/app/models/domain_status.rb index bf0ae2a51..30161c076 100644 --- a/app/models/domain_status.rb +++ b/app/models/domain_status.rb @@ -109,14 +109,12 @@ class DomainStatus < ApplicationRecord DELETE_PROHIBIT_STATES = [ DomainStatus::CLIENT_DELETE_PROHIBITED, DomainStatus::SERVER_DELETE_PROHIBITED, - DomainStatus::CLIENT_UPDATE_PROHIBITED, - DomainStatus::SERVER_UPDATE_PROHIBITED, DomainStatus::PENDING_CREATE, DomainStatus::PENDING_RENEW, DomainStatus::PENDING_TRANSFER, DomainStatus::PENDING_UPDATE, DomainStatus::PENDING_DELETE - ] + ].freeze def epp_code_map { diff --git a/app/models/epp/contact.rb b/app/models/epp/contact.rb index 50ebac065..4cd876d5f 100644 --- a/app/models/epp/contact.rb +++ b/app/models/epp/contact.rb @@ -42,17 +42,12 @@ class Epp::Contact < Contact ) end - def check_availability(codes) + def check_availability(codes, reg:) codes = [codes] if codes.is_a?(String) - res = [] - codes.each do |x| - contact = find_by_epp_code(x) - if contact - res << { code: contact.code, avail: 0, reason: 'in use' } - else - res << { code: x, avail: 1 } - end + codes.map { |c| c.include?(':') ? c : "#{reg}:#{c}" }.map { |c| c.strip.upcase }.each do |x| + c = find_by_epp_code(x) + res << (c ? { code: c.code, avail: 0, reason: 'in use' } : { code: x, avail: 1 }) end res @@ -87,8 +82,11 @@ class Epp::Contact < Contact '2302' => [ # Object exists [:code, :epp_id_taken] ], + '2304' => [ # Status prohibits operation + [:statuses, :delete_prohibited], + ], '2305' => [ # Association exists - [:domains, :exist] + [:domains, :exist], ] } end diff --git a/app/models/epp/domain.rb b/app/models/epp/domain.rb index 6a51b4cfe..f3da8d533 100644 --- a/app/models/epp/domain.rb +++ b/app/models/epp/domain.rb @@ -162,6 +162,9 @@ class Epp::Domain < Domain at[:admin_domain_contacts_attributes] = admin_domain_contacts_attrs(frame, action) at[:tech_domain_contacts_attributes] = tech_domain_contacts_attrs(frame, action) + check_for_same_contacts(at[:admin_domain_contacts_attributes], 'admin') + check_for_same_contacts(at[:tech_domain_contacts_attributes], 'tech') + pw = frame.css('authInfo > pw').text at[:transfer_code] = pw if pw.present? @@ -176,6 +179,11 @@ class Epp::Domain < Domain at end + def check_for_same_contacts(contacts, contact_type) + return unless contacts.uniq.count != contacts.count + + add_epp_error('2306', contact_type, nil, %i[domain_contacts invalid]) + end # Adding legal doc to domain and # if something goes wrong - raise Rollback error @@ -312,6 +320,7 @@ class Epp::Domain < Domain keys = [] return keys if frame.blank? inf_data = DnsSecKeys.new(frame) + add_epp_error('2005', nil, nil, %i[dnskeys invalid]) if not_base64?(inf_data) if action == 'rem' && frame.css('rem > all').first.try(:text) == 'true' @@ -333,6 +342,16 @@ class Epp::Domain < Domain errors.any? ? [] : keys end + def not_base64?(inf_data) + inf_data.key_data.any? do |key| + value = key[:public_key] + + !value.is_a?(String) || Base64.strict_encode64(Base64.strict_decode64(value)) != value + end + rescue ArgumentError + true + end + class DnsSecKeys def initialize(frame) @key_data = [] @@ -381,7 +400,7 @@ class Epp::Domain < Domain def key_data_from(frame) xm_copy frame, KEY_INTERFACE - end + end def ds_data_from(frame) frame.css('dsData').each do |ds_data| @@ -446,7 +465,7 @@ class Epp::Domain < Domain def update(frame, current_user, verify = true) return super if frame.blank? - if discarded? + if discarded? || statuses_blocks_update? add_epp_error('2304', nil, nil, 'Object status prohibits operation') return end @@ -476,7 +495,7 @@ class Epp::Domain < Domain registrant_verification_needed = false # registrant block may not be present, so we need this to rule out false positives if frame.css('registrant').text.present? - registrant_verification_needed = (registrant.code != frame.css('registrant').text) + registrant_verification_needed = verification_needed?(code: frame.css('registrant').text) end if registrant_verification_needed && disputed? @@ -520,6 +539,7 @@ class Epp::Domain < Domain def attach_legal_document(legal_document_data) return unless legal_document_data + return unless legal_document_data[:body] return if legal_document_data[:body].starts_with?(ENV['legal_documents_dir']) legal_documents.create( @@ -592,7 +612,6 @@ class Epp::Domain < Domain statuses.delete(DomainStatus::SERVER_HOLD) statuses.delete(DomainStatus::EXPIRED) - statuses.delete(DomainStatus::SERVER_UPDATE_PROHIBITED) cancel_pending_delete save @@ -778,4 +797,13 @@ class Epp::Domain < Domain result end end + + private + + def verification_needed?(code:) + new_registrant = Registrant.find_by(code: code) + return false if new_registrant.try(:identical_to?, registrant) + + registrant.code != code + end end diff --git a/app/models/invoice.rb b/app/models/invoice.rb index fb625f7b9..73ed88567 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -1,8 +1,8 @@ class Invoice < ApplicationRecord include Versions - include Concerns::Invoice::Cancellable - include Concerns::Invoice::Payable - include Concerns::Invoice::BookKeeping + include Invoice::Cancellable + include Invoice::Payable + include Invoice::BookKeeping belongs_to :buyer, class_name: 'Registrar' has_one :account_activity @@ -34,7 +34,7 @@ class Invoice < ApplicationRecord before_create :calculate_total, unless: :total? before_create :apply_default_buyer_vat_no, unless: :buyer_vat_no? - attribute :vat_rate, ::Type::VATRate.new + attribute :vat_rate, ::Type::VatRate.new def set_invoice_number last_no = Invoice.order(number: :desc).limit(1).pluck(:number).first diff --git a/app/models/legal_document.rb b/app/models/legal_document.rb index e4aab5869..377a9fdde 100644 --- a/app/models/legal_document.rb +++ b/app/models/legal_document.rb @@ -82,7 +82,7 @@ class LegalDocument < ApplicationRecord end end - contact_ids = DomainVersion.where(item_id: orig_legal.documentable_id).distinct. + contact_ids = Version::DomainVersion.where(item_id: orig_legal.documentable_id).distinct. pluck("object->>'registrant_id'", "object_changes->>'registrant_id'", "children->>'tech_contacts'", "children->>'admin_contacts'").flatten.uniq contact_ids = contact_ids.map{|id| diff --git a/app/models/notification.rb b/app/models/notification.rb index e83b2c9da..07e824367 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -25,6 +25,10 @@ class Notification < ApplicationRecord '' end + def registry_lock? + text.include?('has been locked') || text.include?('has been unlocked') + end + private def set_defaults diff --git a/app/models/registrant_user.rb b/app/models/registrant_user.rb index aa41ccff8..f7e85c5af 100644 --- a/app/models/registrant_user.rb +++ b/app/models/registrant_user.rb @@ -9,7 +9,7 @@ class RegistrantUser < User delegate :can?, :cannot?, to: :ability def ident - registrant_ident.to_s.split('-').last + registrant_ident.to_s[3..] end def country @@ -18,6 +18,8 @@ class RegistrantUser < User end def companies(company_register = CompanyRegister::Client.new) + return [] if ident.include?('-') + company_register.representation_rights(citizen_personal_code: ident, citizen_country_code: country.alpha3) end @@ -30,11 +32,15 @@ class RegistrantUser < User Contact.registrant_user_direct_contacts(self) end - def domains + def domains(admin: false) + return Domain.registrant_user_admin_registrant_domains(self) if admin + Domain.registrant_user_domains(self) end - def direct_domains + def direct_domains(admin: false) + return Domain.registrant_user_direct_admin_registrant_domains(self) if admin + Domain.registrant_user_direct_domains(self) end @@ -72,7 +78,7 @@ class RegistrantUser < User return false unless user_data[:last_name] user_data[:country_code] ||= 'EE' - %i[ident country_code].each { |f| user_data[f].upcase! if user_data[f].is_a?(String) } + user_data[:country_code].upcase! if user_data[:country_code].is_a?(String) find_or_create_by_user_data(user_data) end diff --git a/app/models/registrar.rb b/app/models/registrar.rb index 168dfdca7..335fb9115 100644 --- a/app/models/registrar.rb +++ b/app/models/registrar.rb @@ -1,8 +1,8 @@ class Registrar < ApplicationRecord include Versions # version/registrar_version.rb - include Concerns::Registrar::BookKeeping - include Concerns::EmailVerifable - include Concerns::Registrar::LegalDoc + include Registrar::BookKeeping + include EmailVerifable + include Registrar::LegalDoc has_many :domains, dependent: :restrict_with_error has_many :contacts, dependent: :restrict_with_error @@ -30,7 +30,7 @@ class Registrar < ApplicationRecord validates :vat_rate, numericality: { greater_than_or_equal_to: 0, less_than: 100 }, allow_nil: true - attribute :vat_rate, ::Type::VATRate.new + attribute :vat_rate, ::Type::VatRate.new after_initialize :set_defaults validate :correct_email_format, if: proc { |c| c.will_save_change_to_email? } @@ -153,7 +153,7 @@ class Registrar < ApplicationRecord puny = origin.domain.name_puny next unless domains.include?(idn) || domains.include?(puny) || domains.empty? - if origin.domain.nameservers.where(hostname: new_attributes[:hostname]).any? + if domain_not_updatable?(hostname: new_attributes[:hostname], domain: origin.domain) failed_list << idn next end @@ -202,6 +202,10 @@ class Registrar < ApplicationRecord private + def domain_not_updatable?(hostname:, domain:) + domain.nameservers.where(hostname: hostname).any? || domain.bulk_update_prohibited? + end + def set_defaults self.language = Setting.default_language unless language end diff --git a/app/models/tech_domain_contact.rb b/app/models/tech_domain_contact.rb index 92799061c..20f21b6ed 100644 --- a/app/models/tech_domain_contact.rb +++ b/app/models/tech_domain_contact.rb @@ -6,7 +6,7 @@ class TechDomainContact < DomainContact tech_contacts = where(contact: current_contact) tech_contacts.each do |tech_contact| - if tech_contact.domain.discarded? + if tech_contact.domain.bulk_update_prohibited? skipped_domains << tech_contact.domain.name next end @@ -18,7 +18,6 @@ class TechDomainContact < DomainContact skipped_domains << tech_contact.domain.name end end - [affected_domains.sort, skipped_domains.sort] end end diff --git a/app/models/type/vat_rate.rb b/app/models/type/vat_rate.rb index 6a31e389b..142ae0559 100644 --- a/app/models/type/vat_rate.rb +++ b/app/models/type/vat_rate.rb @@ -1,5 +1,5 @@ module Type - class VATRate < ActiveRecord::Type::Decimal + class VatRate < ActiveRecord::Type::Decimal def deserialize(value) super * 100 if value end diff --git a/app/models/version.rb b/app/models/version.rb new file mode 100644 index 000000000..68770a5a1 --- /dev/null +++ b/app/models/version.rb @@ -0,0 +1 @@ +class Version; end diff --git a/app/models/version/account_activity_version.rb b/app/models/version/account_activity_version.rb index b742f7a63..17d8bc8a7 100644 --- a/app/models/version/account_activity_version.rb +++ b/app/models/version/account_activity_version.rb @@ -1,4 +1,4 @@ -class AccountActivityVersion < PaperTrail::Version +class Version::AccountActivityVersion < PaperTrail::Version self.table_name = :log_account_activities self.sequence_name = :log_account_activities_id_seq end diff --git a/app/models/version/account_version.rb b/app/models/version/account_version.rb index b68edd4a5..aca10d41f 100644 --- a/app/models/version/account_version.rb +++ b/app/models/version/account_version.rb @@ -1,4 +1,4 @@ -class AccountVersion < PaperTrail::Version +class Version::AccountVersion < PaperTrail::Version self.table_name = :log_accounts self.sequence_name = :log_accounts_id_seq end diff --git a/app/models/version/action_version.rb b/app/models/version/action_version.rb index bd23d7697..5ca6220b1 100644 --- a/app/models/version/action_version.rb +++ b/app/models/version/action_version.rb @@ -1,4 +1,4 @@ -class ActionVersion < PaperTrail::Version +class Version::ActionVersion < PaperTrail::Version self.table_name = :log_actions self.sequence_name = :log_actions_id_seq end diff --git a/app/models/version/bank_statement_version.rb b/app/models/version/bank_statement_version.rb index ae66f4efe..5a61da3af 100644 --- a/app/models/version/bank_statement_version.rb +++ b/app/models/version/bank_statement_version.rb @@ -1,4 +1,4 @@ -class BankStatementVersion < PaperTrail::Version +class Version::BankStatementVersion < PaperTrail::Version self.table_name = :log_bank_statements self.sequence_name = :log_bank_statements_id_seq end diff --git a/app/models/version/bank_transaction_version.rb b/app/models/version/bank_transaction_version.rb index 93e13be74..63c65e2b8 100644 --- a/app/models/version/bank_transaction_version.rb +++ b/app/models/version/bank_transaction_version.rb @@ -1,4 +1,4 @@ -class BankTransactionVersion < PaperTrail::Version +class Version::BankTransactionVersion < PaperTrail::Version self.table_name = :log_bank_transactions self.sequence_name = :log_bank_transactions_id_seq end diff --git a/app/models/version/billing/price_version.rb b/app/models/version/billing/price_version.rb index 7502c18e2..611405142 100644 --- a/app/models/version/billing/price_version.rb +++ b/app/models/version/billing/price_version.rb @@ -1,7 +1,4 @@ -module Billing - class PriceVersion < PaperTrail::Version - self.table_name = :log_prices - self.sequence_name = :log_prices_id_seq - end +class Version::Billing::PriceVersion < PaperTrail::Version + self.table_name = :log_prices + self.sequence_name = :log_prices_id_seq end - diff --git a/app/models/version/blocked_domain_version.rb b/app/models/version/blocked_domain_version.rb index 82e6b30da..b511445c0 100644 --- a/app/models/version/blocked_domain_version.rb +++ b/app/models/version/blocked_domain_version.rb @@ -1,4 +1,4 @@ -class BlockedDomainVersion < PaperTrail::Version +class Version::BlockedDomainVersion < PaperTrail::Version self.table_name = :log_blocked_domains self.sequence_name = :log_blocked_domains_id_seq end diff --git a/app/models/version/certificate_version.rb b/app/models/version/certificate_version.rb index bcc89e62a..1edd03204 100644 --- a/app/models/version/certificate_version.rb +++ b/app/models/version/certificate_version.rb @@ -1,4 +1,4 @@ -class CertificateVersion < PaperTrail::Version +class Version::CertificateVersion < PaperTrail::Version self.table_name = :log_certificates self.sequence_name = :log_certificates_id_seq end diff --git a/app/models/version/contact_version.rb b/app/models/version/contact_version.rb index 781813302..6c5c70a99 100644 --- a/app/models/version/contact_version.rb +++ b/app/models/version/contact_version.rb @@ -1,7 +1,7 @@ -class ContactVersion < PaperTrail::Version +class Version::ContactVersion < PaperTrail::Version include VersionSession self.table_name = :log_contacts self.sequence_name = :log_contacts_id_seq - + # scope :deleted, -> { where(event: 'destroy') } end diff --git a/app/models/version/dnskey_version.rb b/app/models/version/dnskey_version.rb index c50528e42..ea468194e 100644 --- a/app/models/version/dnskey_version.rb +++ b/app/models/version/dnskey_version.rb @@ -1,4 +1,4 @@ -class DnskeyVersion < PaperTrail::Version +class Version::DnskeyVersion < PaperTrail::Version include VersionSession self.table_name = :log_dnskeys self.sequence_name = :log_dnskeys_id_seq diff --git a/app/models/version/domain_contact_version.rb b/app/models/version/domain_contact_version.rb index 234ff8d9e..d0e1954be 100644 --- a/app/models/version/domain_contact_version.rb +++ b/app/models/version/domain_contact_version.rb @@ -1,4 +1,4 @@ -class DomainContactVersion < PaperTrail::Version +class Version::DomainContactVersion < PaperTrail::Version include VersionSession self.table_name = :log_domain_contacts self.sequence_name = :log_domain_contacts_id_seq diff --git a/app/models/version/domain_version.rb b/app/models/version/domain_version.rb index 27753960a..b2962d1ee 100644 --- a/app/models/version/domain_version.rb +++ b/app/models/version/domain_version.rb @@ -1,4 +1,4 @@ -class DomainVersion < PaperTrail::Version +class Version::DomainVersion < PaperTrail::Version include VersionSession self.table_name = :log_domains diff --git a/app/models/version/invoice_item_version.rb b/app/models/version/invoice_item_version.rb index ffdef5d3e..59a9db6ea 100644 --- a/app/models/version/invoice_item_version.rb +++ b/app/models/version/invoice_item_version.rb @@ -1,4 +1,4 @@ -class InvoiceItemVersion < PaperTrail::Version +class Version::InvoiceItemVersion < PaperTrail::Version self.table_name = :log_invoice_items self.sequence_name = :log_invoice_items_id_seq end diff --git a/app/models/version/invoice_version.rb b/app/models/version/invoice_version.rb index 0b98c873f..037ce7237 100644 --- a/app/models/version/invoice_version.rb +++ b/app/models/version/invoice_version.rb @@ -1,4 +1,4 @@ -class InvoiceVersion < PaperTrail::Version +class Version::InvoiceVersion < PaperTrail::Version self.table_name = :log_invoices self.sequence_name = :log_invoices_id_seq end diff --git a/app/models/version/nameserver_version.rb b/app/models/version/nameserver_version.rb index 01a02c93a..e4d3a8a0f 100644 --- a/app/models/version/nameserver_version.rb +++ b/app/models/version/nameserver_version.rb @@ -1,4 +1,4 @@ -class NameserverVersion < PaperTrail::Version +class Version::NameserverVersion < PaperTrail::Version include VersionSession self.table_name = :log_nameservers self.sequence_name = :log_nameservers_id_seq diff --git a/app/models/version/notification_version.rb b/app/models/version/notification_version.rb index 0b66aabe5..a7eb31ee5 100644 --- a/app/models/version/notification_version.rb +++ b/app/models/version/notification_version.rb @@ -1,4 +1,4 @@ -class NotificationVersion < PaperTrail::Version +class Version::NotificationVersion < PaperTrail::Version include VersionSession self.table_name = :log_notifications self.sequence_name = :log_notifications_id_seq diff --git a/app/models/version/payment_order_version.rb b/app/models/version/payment_order_version.rb index e556f1021..8d0a6d083 100644 --- a/app/models/version/payment_order_version.rb +++ b/app/models/version/payment_order_version.rb @@ -1,4 +1,4 @@ -class PaymentOrderVersion < PaperTrail::Version +class Version::PaymentOrderVersion < PaperTrail::Version self.table_name = :log_payment_orders self.sequence_name = :log_payment_orders_id_seq end diff --git a/app/models/version/registrant_verification_version.rb b/app/models/version/registrant_verification_version.rb index b7dbb8852..4f1d38601 100644 --- a/app/models/version/registrant_verification_version.rb +++ b/app/models/version/registrant_verification_version.rb @@ -1,4 +1,4 @@ -class RegistrantVerificationVersion < PaperTrail::Version +class Version::RegistrantVerificationVersion < PaperTrail::Version include VersionSession self.table_name = :log_registrant_verifications self.sequence_name = :log_registrant_verifications_id_seq diff --git a/app/models/version/registrar_version.rb b/app/models/version/registrar_version.rb index 1e9c9584f..2a55ed212 100644 --- a/app/models/version/registrar_version.rb +++ b/app/models/version/registrar_version.rb @@ -1,4 +1,4 @@ -class RegistrarVersion < PaperTrail::Version +class Version::RegistrarVersion < PaperTrail::Version include VersionSession self.table_name = :log_registrars self.sequence_name = :log_registrars_id_seq diff --git a/app/models/version/reserved_domain_version.rb b/app/models/version/reserved_domain_version.rb index 1f3289b79..db68441ab 100644 --- a/app/models/version/reserved_domain_version.rb +++ b/app/models/version/reserved_domain_version.rb @@ -1,4 +1,4 @@ -class ReservedDomainVersion < PaperTrail::Version +class Version::ReservedDomainVersion < PaperTrail::Version include VersionSession self.table_name = :log_reserved_domains self.sequence_name = :log_reserved_domains_id_seq diff --git a/app/models/version/setting_entry_version.rb b/app/models/version/setting_entry_version.rb index de1e4d1ca..97840771a 100644 --- a/app/models/version/setting_entry_version.rb +++ b/app/models/version/setting_entry_version.rb @@ -1,4 +1,4 @@ -class SettingEntryVersion < PaperTrail::Version +class Version::SettingEntryVersion < PaperTrail::Version self.table_name = :log_setting_entries self.sequence_name = :log_setting_entries end diff --git a/app/models/version/setting_version.rb b/app/models/version/setting_version.rb index d532f8ef4..f93e576a3 100644 --- a/app/models/version/setting_version.rb +++ b/app/models/version/setting_version.rb @@ -1,4 +1,4 @@ -class SettingVersion < PaperTrail::Version +class Version::SettingVersion < PaperTrail::Version include VersionSession self.table_name = :log_settings self.sequence_name = :log_settings_id_seq diff --git a/app/models/version/user_version.rb b/app/models/version/user_version.rb index 13453713b..6737ece7b 100644 --- a/app/models/version/user_version.rb +++ b/app/models/version/user_version.rb @@ -1,4 +1,4 @@ -class UserVersion < PaperTrail::Version +class Version::UserVersion < PaperTrail::Version include VersionSession self.table_name = :log_users self.sequence_name = :log_users_id_seq diff --git a/app/models/version/white_ip_version.rb b/app/models/version/white_ip_version.rb index 0f2ee8a53..44d851628 100644 --- a/app/models/version/white_ip_version.rb +++ b/app/models/version/white_ip_version.rb @@ -1,4 +1,4 @@ -class WhiteIpVersion < PaperTrail::Version +class Version::WhiteIpVersion < PaperTrail::Version include VersionSession self.table_name = :log_white_ips self.sequence_name = :log_white_ips_id_seq diff --git a/app/models/white_ip.rb b/app/models/white_ip.rb index 417633b12..38cee7b6b 100644 --- a/app/models/white_ip.rb +++ b/app/models/white_ip.rb @@ -4,8 +4,13 @@ class WhiteIp < ApplicationRecord validate :valid_ipv4? validate :valid_ipv6? - validate :validate_ipv4_and_ipv6 + before_save :normalize_blank_values + + def normalize_blank_values + %i[ipv4 ipv6].each { |c| self[c].present? || self[c] = nil } + end + def validate_ipv4_and_ipv6 return if ipv4.present? || ipv6.present? errors.add(:base, I18n.t(:ipv4_or_ipv6_must_be_present)) @@ -50,10 +55,10 @@ class WhiteIp < ApplicationRecord def ids_including(ip) ipv4 = ipv6 = [] if check_ip4(ip).present? - ipv4 = select { |white_ip| IPAddr.new(white_ip.ipv4, Socket::AF_INET) === check_ip4(ip) } + ipv4 = select { |white_ip| check_ip4(white_ip.ipv4) === check_ip4(ip) } end if check_ip6(ip).present? - ipv6 = select { |white_ip| IPAddr.new(white_ip.ipv6, Socket::AF_INET6) === check_ip6(ip) } + ipv6 = select { |white_ip| check_ip6(white_ip.ipv6) === check_ip6(ip) } end (ipv4 + ipv6).pluck(:id).flatten.uniq end diff --git a/app/models/whois/record.rb b/app/models/whois/record.rb index 1d827e22a..dc9cc2ba0 100644 --- a/app/models/whois/record.rb +++ b/app/models/whois/record.rb @@ -2,23 +2,34 @@ module Whois class Record < Whois::Server self.table_name = 'whois_records' + def self.without_auctions + ids = Whois::Record.all.select { |record| Auction.where(domain: record.name).blank? } + .pluck(:id) + Whois::Record.where(id: ids) + end + def self.disclaimer Setting.registry_whois_disclaimer end + # rubocop:disable Metrics/AbcSize def update_from_auction(auction) if auction.started? update!(json: { name: auction.domain, status: ['AtAuction'], disclaimer: self.class.disclaimer }) + ToStdout.msg "Updated from auction WHOIS record #{inspect}" elsif auction.no_bids? + ToStdout.msg "Destroying WHOIS record #{inspect}" destroy! elsif auction.awaiting_payment? || auction.payment_received? update!(json: { name: auction.domain, status: ['PendingRegistration'], disclaimer: self.class.disclaimer, registration_deadline: auction.whois_deadline }) + ToStdout.msg "Updated from auction WHOIS record #{inspect}" end end + # rubocop:enable Metrics/AbcSize end end diff --git a/app/models/whois_record.rb b/app/models/whois_record.rb index 3563b9630..9a6229fcb 100644 --- a/app/models/whois_record.rb +++ b/app/models/whois_record.rb @@ -97,6 +97,8 @@ class WhoisRecord < ApplicationRecord end def destroy_whois_record + return if Auction.find_by(domain: name).present? + Whois::Record.where(name: name).delete_all end diff --git a/app/presenters/registrar/domain_list_csv_presenter.rb b/app/presenters/registrar/domain_list_csv_presenter.rb index 46b11f80b..5f32bd022 100644 --- a/app/presenters/registrar/domain_list_csv_presenter.rb +++ b/app/presenters/registrar/domain_list_csv_presenter.rb @@ -1,4 +1,4 @@ -class Registrar::DomainListCSVPresenter +class Registrar::DomainListCsvPresenter def initialize(domains:, view:) @domains = domains @view = view diff --git a/app/views/admin/domain_versions/archive.haml b/app/views/admin/domain_versions/archive.haml index f813f5eb3..46a79190b 100644 --- a/app/views/admin/domain_versions/archive.haml +++ b/app/views/admin/domain_versions/archive.haml @@ -66,7 +66,7 @@ = domain.registrant.name - else - contact = Contact.all_versions_for([domain.registrant_id], version.created_at).first - - if contact.nil? && ver = ContactVersion.where(item_id: domain.registrant_id).last + - if contact.nil? && ver = Version::ContactVersion.where(item_id: domain.registrant_id).last - contact = Contact.new(ver.object.to_h.merge(ver.object_changes.to_h.each_with_object({}) {|(k,v), o| o[k] = v.last })) = contact.try(:name) = " ".html_safe diff --git a/app/views/admin/domains/_search_form.html.erb b/app/views/admin/domains/_search_form.html.erb index bc317ea0b..1b1f50491 100644 --- a/app/views/admin/domains/_search_form.html.erb +++ b/app/views/admin/domains/_search_form.html.erb @@ -6,7 +6,7 @@ <%= f.search_field :name_matches, value: params[:q][:name_matches], class: 'form-control', placeholder: t(:name) %> -
+
<%= f.label :registrant_ident, for: nil %> <%= f.search_field :registrant_ident_eq, class: 'form-control', placeholder: t(:registrant_ident) %> @@ -18,7 +18,7 @@ <%= f.search_field :contacts_ident_eq, class: 'form-control', placeholder: t(:contact_ident) %>
-
+
<%= f.label :nameserver_hostname, for: nil %> <%= f.search_field :nameservers_hostname_eq, class: 'form-control', placeholder: t(:nameserver_hostname) %> @@ -26,7 +26,7 @@
-
+
<%= f.label :registrar_name, for: nil %> <%= f.select :registrar_id_eq, Registrar.all.map { |x| [x, x.id] }, { include_blank: true }, class: 'form-control selectize' %> @@ -38,7 +38,7 @@ <%= f.search_field :valid_to_gteq, value: params[:q][:valid_to_gteq], class: 'form-control js-datepicker', placeholder: t(:valid_to_from) %>
-
+
<%= f.label :valid_to_until, for: nil %> <%= f.search_field :valid_to_lteq, value: params[:q][:valid_to_lteq], class: 'form-control js-datepicker', placeholder: t(:valid_to_until) %> @@ -46,7 +46,7 @@
-
+
<%= label_tag :status, nil, for: nil %> <%= select_tag :statuses_contains, options_for_select(DomainStatus::STATUSES, params[:statuses_contains]), { multiple: true, class: 'form-control js-combobox' } %> @@ -58,13 +58,17 @@ <%= text_field_tag :results_per_page, params[:results_per_page], class: 'form-control', placeholder: t(:results_per_page) %>
-
+
+ <%= link_to t('.download_csv_btn'), admin_domains_path(format: :csv, params: params.permit!), + "data-toggle" => "tooltip", "data-placement" => "bottom", "title" => t('.download_csv_btn'), + class: 'btn btn-default' %> <%= link_to t('.reset_btn'), admin_domains_path, class: 'btn btn-default' %> +
<% end %> diff --git a/app/views/admin/domains/partials/_version.haml b/app/views/admin/domains/partials/_version.haml index da0a0ece1..4533c9293 100644 --- a/app/views/admin/domains/partials/_version.haml +++ b/app/views/admin/domains/partials/_version.haml @@ -23,7 +23,7 @@ - admin_contacts = domain.admin_contacts - registrant = domain.registrant - unless registrant - - ver = ContactVersion.where(item_id: domain.registrant_id).where(event: :destroy).last + - ver = Version::ContactVersion.where(item_id: domain.registrant_id).where(event: :destroy).last - registrant = ver.reify - registrant.version_loader = ver - registrant = [registrant] diff --git a/app/views/admin/repp_logs/show.haml b/app/views/admin/repp_logs/show.haml index bbaae977f..9bb9ea52e 100644 --- a/app/views/admin/repp_logs/show.haml +++ b/app/views/admin/repp_logs/show.haml @@ -1,6 +1,6 @@ - content_for :actions do = link_to(t(:back), :back, class: 'btn btn-primary') -= render 'shared/title', name: t(:repp_log) += render 'shared/title', name: t('.title') .row .col-md-12 diff --git a/app/views/epp/poll/poll_req.xml.builder b/app/views/epp/poll/poll_req.xml.builder index 664327dae..a58b082c5 100644 --- a/app/views/epp/poll/poll_req.xml.builder +++ b/app/views/epp/poll/poll_req.xml.builder @@ -15,12 +15,22 @@ xml.epp_head do end if @object end - if @notification.action&.contact - render(partial: 'epp/poll/action', - locals: { - builder: xml, - action: @notification.action - }) + if @notification.action&.contact || @notification.registry_lock? + if @notification.registry_lock? + state = @notification.text.include?('unlocked') ? 'unlock' : 'lock' + xml.extension do + xml.tag!('changePoll:changeData', + 'xmlns:changePoll': 'https://epp.tld.ee/schema/changePoll-1.0.xsd') do + xml.tag!('changePoll:operation', state) + end + end + else + render(partial: 'epp/poll/action', + locals: { + builder: xml, + action: @notification.action, + }) + end end render('epp/shared/trID', builder: xml) diff --git a/app/views/registrant/contacts/_api_errors.html.erb b/app/views/registrant/contacts/_api_errors.html.erb deleted file mode 100644 index 35617fa99..000000000 --- a/app/views/registrant/contacts/_api_errors.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -
-
    - <% errors.each_value do |errors| %> -
  • <%= errors.join('
    ') %>
  • - <% end %> -
-
\ No newline at end of file diff --git a/app/views/registrant/contacts/_form.html.erb b/app/views/registrant/contacts/_form.html.erb deleted file mode 100644 index f203f39e8..000000000 --- a/app/views/registrant/contacts/_form.html.erb +++ /dev/null @@ -1,64 +0,0 @@ -<%= form_for [:registrant, domain, @contact], html: { class: 'form-horizontal' } do |f| %> - <% if @errors.present? %> - <%= render 'api_errors', errors: @errors %> - <% end %> - -
-
- <%= f.label :name %> -
- -
- <%= f.text_field :name, required: true, autofocus: true, class: 'form-control' %> -
-
- -
-
- <%= f.label :email %> -
- -
- <%= f.email_field :email, required: true, class: 'form-control' %> -
-
- -
-
- <%= f.label :phone %> -
- -
- <%= f.text_field :phone, required: true, class: 'form-control' %> -
-
- - <% if Contact.address_processing? %> -
-
<%= t '.address' %>
-
- <%= render 'registrant/contacts/form/address', f: f %> -
-
- <% end %> - - <% if fax_enabled? %> -
-
- <%= f.label :fax %> -
- -
- <%= f.text_field :fax, class: 'form-control' %> -
-
- <% end %> - -
- -
-
- <%= button_tag t('.submit_btn'), class: 'btn btn-success' %> -
-
-<% end %> \ No newline at end of file diff --git a/app/views/registrant/contacts/edit.html.erb b/app/views/registrant/contacts/edit.html.erb deleted file mode 100644 index 0a453ded1..000000000 --- a/app/views/registrant/contacts/edit.html.erb +++ /dev/null @@ -1,12 +0,0 @@ - - - - -<%= render 'form' %> \ No newline at end of file diff --git a/app/views/registrant/contacts/form/_address.html.erb b/app/views/registrant/contacts/form/_address.html.erb deleted file mode 100644 index a43784d3f..000000000 --- a/app/views/registrant/contacts/form/_address.html.erb +++ /dev/null @@ -1,51 +0,0 @@ -
-
- <%= f.label :street %> -
- -
- <%= f.text_field :street, required: true, class: 'form-control' %> -
-
- -
-
- <%= f.label :zip %> -
- -
- <%= f.text_field :zip, required: true, class: 'form-control' %> -
-
- -
-
- <%= f.label :city %> -
- -
- <%= f.text_field :city, required: true, class: 'form-control' %> -
-
- -
-
- <%= f.label :state %> -
- -
- <%= f.text_field :state, class: 'form-control' %> -
-
- -
-
- <%= f.label :country_code, 'Country' %> -
- -
- <%= f.select :country_code, SortedCountry.all_options(f.object.country_code), {}, - required: true, - class: 'form-control' %> -
-
\ No newline at end of file diff --git a/app/views/registrant/contacts/show.html.erb b/app/views/registrant/contacts/show.html.erb deleted file mode 100644 index 1f0a87b5f..000000000 --- a/app/views/registrant/contacts/show.html.erb +++ /dev/null @@ -1,42 +0,0 @@ - - - - -
-
- <%= render 'registrant/contacts/show/general' %> -
- -
- <%= render 'registrant/contacts/show/address' %> -
-
- -
-
- <%= render 'registrant/contacts/show/statuses', contact: @contact %> -
-
- -
-
- <%= render 'registrant/contacts/show/domains', contact: @contact %> -
-
\ No newline at end of file diff --git a/app/views/registrant/contacts/show/_address.html.erb b/app/views/registrant/contacts/show/_address.html.erb deleted file mode 100644 index c9bc80150..000000000 --- a/app/views/registrant/contacts/show/_address.html.erb +++ /dev/null @@ -1,31 +0,0 @@ -
-
-

- <%= t '.header' %> -

-
- -
-
- <% if @contact.org_name.present? %> -
<%= Contact.human_attribute_name :org_name %>
-
<%= @contact.org_name %>
- <% end %> - -
<%= Contact.human_attribute_name :street %>
-
<%= @contact.street %>
- -
<%= Contact.human_attribute_name :city %>
-
<%= @contact.city %>
- -
<%= Contact.human_attribute_name :zip %>
-
<%= @contact.zip %>
- -
<%= Contact.human_attribute_name :state %>
-
<%= @contact.state %>
- -
<%= Contact.human_attribute_name :country %>
-
<%= @contact.country %>
-
-
-
\ No newline at end of file diff --git a/app/views/registrant/contacts/show/_domain.html.erb b/app/views/registrant/contacts/show/_domain.html.erb deleted file mode 100644 index 83b7f49d5..000000000 --- a/app/views/registrant/contacts/show/_domain.html.erb +++ /dev/null @@ -1,6 +0,0 @@ - - <%= link_to domain.name, registrant_domain_path(domain) %> - <%= link_to domain.registrar, registrant_registrar_path(domain.registrar) %> - <%= l domain.valid_to %> - <%= domain.roles.join(", ") %> - \ No newline at end of file diff --git a/app/views/registrant/contacts/show/_domains.html.erb b/app/views/registrant/contacts/show/_domains.html.erb deleted file mode 100644 index d783b55b2..000000000 --- a/app/views/registrant/contacts/show/_domains.html.erb +++ /dev/null @@ -1,54 +0,0 @@ -<% domains = contact.all_domains(page: params[:domain_page], per: 20, - params: domain_filter_params.to_h, requester: @requester_contact) %> - -
-
-
-
- <%= t '.header' %> -
- -
- <%= form_tag request.path, method: :get, class: 'form-inline' do %> - <%= select_tag :domain_filter, - options_for_select(%w(Registrant AdminDomainContact TechDomainContact), - selected: params[:domain_filter]), - include_blank: t('.all'), - class: 'form-control' %> - - <% end %> -
-
-
- -
- - - - - - - - - - - - <%= render partial: 'registrant/contacts/show/domain', collection: domains %> - -
- <%= custom_sort_link Domain.human_attribute_name(:name), :name %> - - <%= custom_sort_link Registrar.model_name.human, :registrar_name %> - - <%= custom_sort_link Domain.human_attribute_name(:valid_to), :valid_to %> - - <%= custom_sort_link Domain.human_attribute_name(:roles), :roles %> -
-
- - -
diff --git a/app/views/registrant/contacts/show/_general.html.erb b/app/views/registrant/contacts/show/_general.html.erb deleted file mode 100644 index b61d2f50e..000000000 --- a/app/views/registrant/contacts/show/_general.html.erb +++ /dev/null @@ -1,48 +0,0 @@ -
-
-

- <%= t '.header' %> -

-
- -
-
-
<%= Contact.human_attribute_name :code %>
-
<%= @contact.code %>
- -
<%= Contact.human_attribute_name :name %>
-
<%= @contact.name %>
- -
<%= Contact.human_attribute_name :auth_info %>
-
- <%= tag :input, type: 'text', value: @contact.auth_info, readonly: true, - class: 'form-control input-sm' %> -
- -
<%= Contact.human_attribute_name :ident %>
-
<%= ident_for(@contact) %>
- -
<%= Contact.human_attribute_name :email %>
-
<%= @contact.email %>
- -
<%= Contact.human_attribute_name :phone %>
-
<%= @contact.phone %>
- - <% if @contact.fax %> -
<%= Contact.human_attribute_name :fax %>
-
<%= @contact.fax %>
- <% end %> - -
<%= Contact.human_attribute_name :created_at %>
-
<%= l @contact.created_at %>
- -
<%= Contact.human_attribute_name :updated_at %>
-
<%= l @contact.updated_at %>
- -
<%= Registrar.model_name.human %>
-
- <%= link_to @contact.registrar, registrant_registrar_path(@contact.registrar) %> -
-
-
-
\ No newline at end of file diff --git a/app/views/registrant/contacts/show/_search.html.erb b/app/views/registrant/contacts/show/_search.html.erb deleted file mode 100644 index f44fa322f..000000000 --- a/app/views/registrant/contacts/show/_search.html.erb +++ /dev/null @@ -1,6 +0,0 @@ -<%= search_form_for [:registrant, @q] do |f| %> - <%= f.search_field :name_cont %> - <%= f.submit do %> - - <% end %> -<% end %> \ No newline at end of file diff --git a/app/views/registrant/contacts/show/_statuses.html.erb b/app/views/registrant/contacts/show/_statuses.html.erb deleted file mode 100644 index 07db6bc87..000000000 --- a/app/views/registrant/contacts/show/_statuses.html.erb +++ /dev/null @@ -1,25 +0,0 @@ -
-
- <%= t '.header' %> -
- -
- - - - - - - - - - <% contact.statuses.each do |status| %> - - - - - <% end %> - -
<%= t '.status' %><%= t '.notes' %>
<%= status %><%= contact.status_notes[status] %>
-
-
\ No newline at end of file diff --git a/app/views/registrant/domain_delete_confirms/show.haml b/app/views/registrant/domain_delete_confirms/show.haml deleted file mode 100644 index fffc03219..000000000 --- a/app/views/registrant/domain_delete_confirms/show.haml +++ /dev/null @@ -1,44 +0,0 @@ -- if params[:confirmed].present? - .row - .col-md-12 - %h1= t(:domain_delete_confirmed_title) - .row - .col-md-12 - %p= t(:domain_delete_confirmed_body) -- elsif params[:rejected].present? - .row - .col-md-12 - %h1= t(:domain_delete_rejected_title) - .row - .col-md-12 - %p= t(:domain_delete_rejected_body) -- else - - if @domain.present? - .row - .col-md-12 - %h1= t(:domain_delete_title) - .row - .col-md-12 - %p= t(:domain_delete_body) - - %hr - .row - .col-md-12.text-center.confirmation - .column-keys - %p= t(:domain_name) + ':' - %p= t('.registrant') + ':' - .column-values - %p= @domain.name - %p= "#{@domain.registrant.name} (#{@domain.registrant.ident})" - - .row - .col-md-12.text-center - .confirmation - = form_for registrant_domain_delete_confirm_path(@domain.id), method: :patch do |f| - = hidden_field_tag :token, params[:token] - = f.button t(:confirm_domain_delete), name: 'confirmed', class: 'btn btn-primary' - = f.button t(:reject_domain_delete), name: 'rejected', class: 'btn btn-warning' - %hr - - else - %h1= t(:not_valid_domain_verification_title).html_safe - %p= t(:not_valid_domain_verification_body).html_safe diff --git a/app/views/registrant/domain_update_confirms/show.haml b/app/views/registrant/domain_update_confirms/show.haml deleted file mode 100644 index 5f7a978ce..000000000 --- a/app/views/registrant/domain_update_confirms/show.haml +++ /dev/null @@ -1,46 +0,0 @@ -- if params[:confirmed].present? - .row - .col-md-12 - %h1= t(:domain_registrant_change_confirmed_title) - .row - .col-md-12 - %p= t(:domain_registrant_change_confirmed_body) -- elsif params[:rejected].present? - .row - .col-md-12 - %h1= t(:domain_registrant_change_rejected_title) - .row - .col-md-12 - %p= t(:domain_registrant_change_rejected_body) -- else - - if @domain.present? - .row - .col-md-12 - %h1= t(:domain_registrant_change_title) - .row - .col-md-12 - %p= t(:domain_registrant_change_body) - - %hr - .row - .col-md-12.text-center.confirmation - .column-keys - %p= t(:domain_name) + ':' - %p= t(:current_registrant) + ':' - %p= t(:new_pending_registrant) + ':' - .column-values - %p= @domain.name - %p= "#{@domain.registrant.name} (#{@domain.registrant.ident})" - %p= "#{@domain.pending_registrant.try(:name)} (#{@domain.pending_registrant.try(:ident)})" - - .row - .col-md-12.text-center - .confirmation - = form_for registrant_domain_update_confirm_path(@domain.id), method: :patch do |f| - = hidden_field_tag :token, params[:token] - = f.button t(:confirm_domain_registrant_update), name: 'confirmed', class: 'btn btn-primary' - = f.button t(:reject_domain_registrant_update), name: 'rejected', class: 'btn btn-warning' - %hr - - else - %h1= t(:not_valid_domain_verification_title).html_safe - %p= t(:not_valid_domain_verification_body).html_safe diff --git a/app/views/registrant/domains/_domain.html.erb b/app/views/registrant/domains/_domain.html.erb deleted file mode 100644 index 8cc8a490b..000000000 --- a/app/views/registrant/domains/_domain.html.erb +++ /dev/null @@ -1,9 +0,0 @@ - - <%= link_to domain, registrant_domain_path(domain) %> - - <%= link_to domain.registrant.name, - registrant_domain_contact_path(domain, domain.registrant) %> - - <%= l domain.expire_time %> - <%= link_to domain.registrar, registrant_registrar_path(domain.registrar) %> - diff --git a/app/views/registrant/domains/confirmation.haml b/app/views/registrant/domains/confirmation.haml deleted file mode 100644 index b1bc0cb2f..000000000 --- a/app/views/registrant/domains/confirmation.haml +++ /dev/null @@ -1,13 +0,0 @@ -- content_for :actions do - = render 'shared/title', name: @domain.name - -.row - .col-md-12 - .panel.panel-default - .panel-heading - %h3.panel-title= t('.header') - .panel-body - .input-group.input-group-lg - %span#sizing-addon1.input-group-addon.glyphicon.glyphicon-link - %input.form-control{"aria-describedby" => "sizing-addon1", type: "text", value: @confirmation_url} - diff --git a/app/views/registrant/domains/index.html.erb b/app/views/registrant/domains/index.html.erb deleted file mode 100644 index 1254bfbc8..000000000 --- a/app/views/registrant/domains/index.html.erb +++ /dev/null @@ -1,102 +0,0 @@ - - -
-
- <%= search_form_for [:registrant, @q], html: { class: 'search-form', autocomplete: 'off' } do |f| %> -
-
-
- <%= f.label :name, for: nil %> - <%= f.search_field :name_matches, value: params[:q][:name_matches], class: 'form-control', placeholder: t(:name) %> -
-
-
-
- <%= f.label t(:registrant_ident), for: nil %> - <%= f.search_field :registrant_ident_eq, class: 'form-control', placeholder: t(:registrant_ident) %> -
-
- -
-
- <%= label_tag t(:results_per_page) %> - <%= text_field_tag :results_per_page, params[:results_per_page], class: 'form-control', placeholder: t(:results_per_page) %> -
-
-
-
-
-
- <%= f.label t(:valid_to_from), for: nil %> - <%= f.search_field :valid_to_gteq, value: params[:q][:valid_to_gteq], class: 'form-control js-datepicker', placeholder: t(:valid_to_from) %> -
-
-
-
- <%= f.label t(:valid_to_until), for: nil %> - <%= f.search_field :valid_to_lteq, value: params[:q][:valid_to_lteq], class: 'form-control js-datepicker', placeholder: t(:valid_to_until) %> -
-
-
- -
-
- - <%= button_tag t('.download_pdf_btn'), - formaction: registrant_domains_path(format: :pdf), - name: nil, - class: 'btn btn-default' %> - <%= button_tag t('.download_csv_btn'), - formaction: registrant_domains_path(format: :csv), - name: nil, - class: 'btn btn-default' %> - <%= link_to t('.reset_btn'), registrant_domains_path, - class: 'btn btn-default' %> -
-
- <% end %> -
-
-
-
-
-
- - - - - - - - - - - - <%= render @domains %> - -
- <%= sort_link(@q, 'name') %> - - <%= sort_link(@q, 'registrant_name', t('.registrant')) %> - - <%= sort_link(@q, 'valid_to', t(:valid_to)) %> - - <%= sort_link(@q, 'registrar_name', t(:registrar_name)) %> -
-
-
-
- <%= paginate @domains %> -
-
- -
-
diff --git a/app/views/registrant/domains/list_pdf.html.erb b/app/views/registrant/domains/list_pdf.html.erb deleted file mode 100644 index 4ce4f5ed0..000000000 --- a/app/views/registrant/domains/list_pdf.html.erb +++ /dev/null @@ -1,32 +0,0 @@ - - - -
-
-
- - - - - - - - - - - - <% @domains.each do |domain| %> - - - - - - - <% end %> - -
<%= Domain.human_attribute_name :name %><%= Registrant.model_name.human %><%= Domain.human_attribute_name :valid_to %><%= Registrar.model_name.human %>
<%= domain.name %><%= domain.registrant %><%= l(domain.valid_to, format: :short) %><%= domain.registrar %>
-
-
-
- - diff --git a/app/views/registrant/domains/partials/_dnskeys.haml b/app/views/registrant/domains/partials/_dnskeys.haml deleted file mode 100644 index ddd95e952..000000000 --- a/app/views/registrant/domains/partials/_dnskeys.haml +++ /dev/null @@ -1,18 +0,0 @@ -.panel.panel-default - .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 diff --git a/app/views/registrant/domains/partials/_domain_contact.html.erb b/app/views/registrant/domains/partials/_domain_contact.html.erb deleted file mode 100644 index e4eaf7115..000000000 --- a/app/views/registrant/domains/partials/_domain_contact.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -<% contact = domain_contact.contact %> - - - <%= link_to contact, registrant_domain_contact_path(domain, contact) %> - <%= contact.code %> - <%= contact.email %> - \ No newline at end of file diff --git a/app/views/registrant/domains/partials/_domain_contacts.html.erb b/app/views/registrant/domains/partials/_domain_contacts.html.erb deleted file mode 100644 index 3876e2546..000000000 --- a/app/views/registrant/domains/partials/_domain_contacts.html.erb +++ /dev/null @@ -1,24 +0,0 @@ -
-
- <%= t ".header_#{domain_contacts.model_name.plural.underscore}" %> -
- -
- - - - - - - - - - - <%= render partial: 'registrant/domains/partials/domain_contact', - collection: domain_contacts, - locals: { domain: domain } %> - -
<%= Contact.human_attribute_name :name %><%= Contact.human_attribute_name :code %><%= Contact.human_attribute_name :email %>
-
-
\ No newline at end of file diff --git a/app/views/registrant/domains/partials/_general.html.erb b/app/views/registrant/domains/partials/_general.html.erb deleted file mode 100644 index 38995be01..000000000 --- a/app/views/registrant/domains/partials/_general.html.erb +++ /dev/null @@ -1,38 +0,0 @@ -
-
-

- <%= t(:general) %> -

-
- -
-
-
<%= t(:name) %>
-
<%= @domain.name %>
- -
<%= Domain.human_attribute_name :registered_at %>
-
<%= l(@domain.registered_at) %>
- -
<%= Registrar.model_name.human %>
-
<%= link_to(@domain.registrar, registrant_registrar_path(@domain.registrar)) %>
- -
<%= Domain.human_attribute_name :transfer_code %>
-
- <%= tag :input, type: 'text', value: @domain.transfer_code, readonly: true, - class: 'form-control input-sm' %> -
- -
<%= t(:valid_to) %>
-
<%= l(@domain.valid_to) %>
- -
<%= Domain.human_attribute_name :outzone_at %>
-
<%= l(@domain.outzone_at) %>
- -
<%= Domain.human_attribute_name :delete_date %>
-
<%= l @domain.delete_date %>
- -
<%= Domain.human_attribute_name :force_delete_date %>
-
<%= l @domain.force_delete_date %>
-
-
-
diff --git a/app/views/registrant/domains/partials/_legal_documents.haml b/app/views/registrant/domains/partials/_legal_documents.haml deleted file mode 100644 index 7d740977b..000000000 --- a/app/views/registrant/domains/partials/_legal_documents.haml +++ /dev/null @@ -1,14 +0,0 @@ -.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 deleted file mode 100644 index 0bc22732d..000000000 --- a/app/views/registrant/domains/partials/_nameservers.haml +++ /dev/null @@ -1,16 +0,0 @@ -.panel.panel-default - .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 diff --git a/app/views/registrant/domains/partials/_registrant.html.erb b/app/views/registrant/domains/partials/_registrant.html.erb deleted file mode 100644 index f02a2eb4e..000000000 --- a/app/views/registrant/domains/partials/_registrant.html.erb +++ /dev/null @@ -1,26 +0,0 @@ -
-
- <%= t '.header' %> -
- -
-
-
<%= Registrant.human_attribute_name :name %>
-
- <%= link_to registrant.name, registrant_domain_contact_path(domain, registrant) %> -
- -
<%= Registrant.human_attribute_name :code %>
-
<%= registrant.code %>
- -
<%= Registrant.human_attribute_name :ident %>
-
<%= registrant.ident %>
- -
<%= Registrant.human_attribute_name :email %>
-
<%= registrant.email %>
- -
<%= Registrant.human_attribute_name :phone %>
-
<%= registrant.phone %>
-
-
-
\ No newline at end of file diff --git a/app/views/registrant/domains/partials/_statuses.haml b/app/views/registrant/domains/partials/_statuses.haml deleted file mode 100644 index 10fc795eb..000000000 --- a/app/views/registrant/domains/partials/_statuses.haml +++ /dev/null @@ -1,18 +0,0 @@ -#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 [DomainStatus::PENDING_UPDATE, DomainStatus::PENDING_DELETE_CONFIRMATION].include?(status) && @domain.pending_json.present? - = link_to(status, confirmation_registrant_domain_path(@domain)) - - else - = status - %td= @domain.status_notes[status] diff --git a/app/views/registrant/domains/show.html.erb b/app/views/registrant/domains/show.html.erb deleted file mode 100644 index 81ca04b51..000000000 --- a/app/views/registrant/domains/show.html.erb +++ /dev/null @@ -1,52 +0,0 @@ - - - - -
-
- <%= render 'registrant/domains/partials/general' %> -
- -
- <%= render partial: 'registrant/domains/partials/registrant', - locals: { registrant: @domain.registrant, domain: @domain } %> -
-
- -
-
- <%= render 'registrant/domains/partials/domain_contacts', - domain: @domain, - domain_contacts: @domain.tech_domain_contacts %> -
-
- -
-
- <%= render 'registrant/domains/partials/domain_contacts', - domain: @domain, - domain_contacts: @domain.admin_domain_contacts %> -
-
- -
-
- <%= render 'registrant/domains/partials/statuses' %> -
-
- -
-
- <%= render 'registrant/domains/partials/nameservers' %> -
-
- -
-
- <%= render 'registrant/domains/partials/dnskeys' %> -
-
diff --git a/app/views/registrant/registrars/show.haml b/app/views/registrant/registrars/show.haml deleted file mode 100644 index f5e0f40f4..000000000 --- a/app/views/registrant/registrars/show.haml +++ /dev/null @@ -1,44 +0,0 @@ -= 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= Registrar.human_attribute_name :name - %dd= @registrar.name - - %dt= Registrar.human_attribute_name :reg_no - %dd= @registrar.reg_no - - %dt= Registrar.human_attribute_name :vat_no - %dd= @registrar.vat_no - - %dt= Registrar.human_attribute_name :code - %dd= @registrar.code - - .col-md-6 - .panel.panel-default - .panel-heading - %h3.panel-title= t(:contact) - .panel-body - %dl.dl-horizontal - %dt= Registrar.human_attribute_name :country - %dd= @registrar.country - - %dt= Registrar.human_attribute_name :address - %dd= @registrar.address - - %dt= Registrar.human_attribute_name :phone - %dd= @registrar.phone - - %dt= Registrar.human_attribute_name :email - %dd= @registrar.email diff --git a/app/views/registrant/sessions/new.html.erb b/app/views/registrant/sessions/new.html.erb deleted file mode 100644 index 9f7af3254..000000000 --- a/app/views/registrant/sessions/new.html.erb +++ /dev/null @@ -1,13 +0,0 @@ -
- -
diff --git a/app/views/registrant/whois/index.haml b/app/views/registrant/whois/index.haml deleted file mode 100644 index 5b1e64efa..000000000 --- a/app/views/registrant/whois/index.haml +++ /dev/null @@ -1,17 +0,0 @@ -= render 'shared/title', name: t(:whois) - -.row - .col-md-12{style: 'margin-bottom: -15px;'} - = form_tag registrant_whois_path, class: 'form-horizontal', method: :get do - .col-md-11 - .form-group - = text_field_tag :domain_name, params[:domain_name], class: 'form-control', placeholder: t(:domain_name), autocomplete: 'off', autofocus: true - .col-md-1.text-right.text-center-xs - .form-group - %button.btn.btn-default -   - %span.glyphicon.glyphicon-search -   -%hr -- if @domain - %pre= @domain.body diff --git a/app/views/registrar/account_activities/index.html.erb b/app/views/registrar/account_activities/index.html.erb index c5eaf2063..aefcdd47f 100644 --- a/app/views/registrar/account_activities/index.html.erb +++ b/app/views/registrar/account_activities/index.html.erb @@ -14,7 +14,7 @@ - + @@ -45,6 +48,9 @@ + <% end %> diff --git a/app/views/registrar/bulk_change/_admin_contact_form.html.erb b/app/views/registrar/bulk_change/_admin_contact_form.html.erb new file mode 100644 index 000000000..77734e872 --- /dev/null +++ b/app/views/registrar/bulk_change/_admin_contact_form.html.erb @@ -0,0 +1,65 @@ +<%= form_tag registrar_admin_contacts_path, method: :patch, class: 'form-horizontal' do %> + <% if @error %> +
+ <%= @error %> +
+ <% end %> + +
+
+
+

<%= t '.comment' %>

+
+
+
+ <%= label_tag :current_contact_id, t('.current_contact_id') %> +
+ +
+ <%= text_field_tag :current_contact_id, params[:current_contact_id], + list: :contacts, + required: true, + autofocus: true, + class: 'form-control' %> +
+
+ +
+
+ <%= label_tag :new_contact_id, t('.new_contact_id') %> +
+ +
+ <%= text_field_tag :new_contact_id, params[:new_contact_id], + list: :contacts, + required: true, + class: 'form-control' %> +
+
+ +
+
+ +
+
+ +
+
+ <%= t '.help_btn' %> +
+
+ <%= t '.help' %> +
+
+
+
+<% end %> + + + <% available_contacts.each do |data| %> + + <% end %> + diff --git a/app/views/registrar/bulk_change/_tech_contact_form.html.erb b/app/views/registrar/bulk_change/_tech_contact_form.html.erb index 2848e3634..789db92ba 100644 --- a/app/views/registrar/bulk_change/_tech_contact_form.html.erb +++ b/app/views/registrar/bulk_change/_tech_contact_form.html.erb @@ -10,7 +10,7 @@ <%= label_tag :current_contact_id, t('.current_contact_id') %> -
+
<%= text_field_tag :current_contact_id, params[:current_contact_id], list: :contacts, required: true, @@ -24,7 +24,7 @@ <%= label_tag :new_contact_id, t('.new_contact_id') %>
-
+
<%= text_field_tag :new_contact_id, params[:new_contact_id], list: :contacts, required: true, diff --git a/app/views/registrar/bulk_change/new.html.erb b/app/views/registrar/bulk_change/new.html.erb index e61270b6d..f3095a53d 100644 --- a/app/views/registrar/bulk_change/new.html.erb +++ b/app/views/registrar/bulk_change/new.html.erb @@ -12,6 +12,10 @@ <%= t '.technical_contact' %> +
  • + <%= t '.admin_contact' %> +
  • +
  • <%= t '.nameserver' %>
  • @@ -31,6 +35,11 @@ <%= render 'tech_contact_form', available_contacts: available_contacts %>
    +
    + <%= render 'admin_contact_form', available_contacts: available_contacts %> +
    +
    <%= render 'nameserver_form' %>
    diff --git a/config/application.rb b/config/application.rb index a5fb17c9d..0ab5aa8bb 100644 --- a/config/application.rb +++ b/config/application.rb @@ -17,7 +17,7 @@ end module DomainNameRegistry class Application < Rails::Application config.load_defaults 6.0 - config.autoloader = :classic # Do not use zeitwerk for now + config.autoloader = :zeitwerk # Do not use zeitwerk for now # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers @@ -35,9 +35,11 @@ module DomainNameRegistry # config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')] # Autoload all model subdirs - config.autoload_paths += Dir[Rails.root.join('app', 'models', '**/')] - config.autoload_paths += Dir[Rails.root.join('app', 'interactions', '**/')] + # config.autoload_paths += Dir[Rails.root.join('app', 'models', '**/')] + # config.autoload_paths += Dir[Rails.root.join('app', 'lib', '**/')] + # config.autoload_paths += Dir[Rails.root.join('app', 'interactions', '**/')] config.eager_load_paths << config.root.join('lib', 'validators') + config.eager_load_paths << config.root.join('app', 'lib') config.watchable_dirs['lib'] = %i[rb] config.active_record.schema_format = :sql @@ -70,8 +72,7 @@ module DomainNameRegistry } config.action_mailer.default_options = { from: ENV['action_mailer_default_from'] } - require "#{Rails.root}/app/mailers/interceptors/punycode_interceptor" - ActionMailer::Base.register_interceptor(PunycodeInterceptor) + config.action_mailer.interceptors = ["Interceptors::PunycodeInterceptor"] config.action_view.default_form_builder = 'DefaultFormBuilder' config.secret_key_base = Figaro.env.secret_key_base diff --git a/config/application.yml.sample b/config/application.yml.sample index 5885c47a2..88fc28a0d 100644 --- a/config/application.yml.sample +++ b/config/application.yml.sample @@ -87,8 +87,11 @@ sk_digi_doc_service_name: 'Testimine' registrant_api_base_url: registrant_api_auth_allowed_ips: '127.0.0.1, 0.0.0.0' #ips, separated with commas -# Bounces API -api_shared_key: testkey +# Shared key for REST-WHOIS Bounces API incl. CERT +rwhois_bounces_api_shared_key: testkey + +# Link to REST-WHOIS API +rwhois_internal_api_shared_key: testkey # Base URL (inc. https://) of REST registrant portal # Leave blank to use internal registrant portal @@ -167,7 +170,7 @@ tara_issuer: 'https://tara-test.ria.ee' tara_identifier: 'identifier' tara_secret: 'secret' tara_redirect_uri: 'redirect_url' -tara_keys: "{\"kty\":\"RSA\",\"kid\":\"de6cc4\",\"n\":\"jWwAjT_03ypme9ZWeSe7c-jY26NO50Wo5I1LBnPW2JLc0dPMj8v7y4ehiRpClYNTaSWcLd4DJmlKXDXXudEUWwXa7TtjBFJfzlZ-1u0tDvJ-H9zv9MzO7UhUFytztUEMTrtStdhGbzkzdEZZCgFYeo2i33eXxzIR1nGvI05d9Y-e_LHnNE2ZKTa89BC7ZiCXq5nfAaCgQna_knh4kFAX-KgiPRAtsiDHcAWKcBY3qUVcb-5XAX8p668MlGLukzsh5tFkQCbJVyNtmlbIHdbGvVHPb8C0H3oLYciv1Fjy_tS1lO7OT_cb3GVp6Ql-CG0uED_8pkpVtfsGRviub4_ElQ\",\"e\":\"AQAB\"}" +tara_keys: "{\"kty\":\"RSA\",\"kid\":\"public:xWbbVoYq9EwMqphp\",\"n\":\"2vlgaxaUJYUWjkNM_b-ruADW3gyGnkPvxDyEXWeLyP668vn5aTrSdZ42psr6Vpu6V1MEjMr27bnE7swqndfmspqJHKlp47fO9orWWNGmrHFtClxU36wqFiIg9V39hbHdoXqZVdLywwjx6KLgsuYff95KvwfDqUK9IxxADm91ckD9m9aoQaPTrn8KsB9uhkyEchejNHRg7EGZDvWHF-aiQHCMnieSowiapPd7kTYGemPMheVyY_Zwvyya8DkvjnVa8HlrmbzjMjGdSRq5dVL0lCxb4-OlZ-QZuORUBqZ5xEAhWg2Jl6oG0slj3z8l_fd7l2oj7THNoepYWTnzUDxsN1hvRLzFnJh8MNUklYHWf8CFrwmPdqGDs0jeLP2v7X8LJeQ-Ly3GHsUBai1aVORZXCHq1Tzt2XyQhvPVt_3WoaVKJBi4hjz0CLKlSE0eUv9TWL58CU76tU98dxOwSb6hhqEu3xn6mLApyyEZzeUdYdJutDFQuTYz2pb1yqMFqlp2LHa49p7Q5TvBp4pKOxwjrqnlKTsasL8BU2vA9xHuEEYttVzAPWjH_5-BfoJ8GKQTLaXc6LOmWIZcMDVM8QEOkLXQdUtlaPVz-2wl9Q_FwhoBzXSZujEYQVcSZznxIdNyV4nvn2mo56isITX18PTcdyZ4V-wWlS5PuUNVVRQHWE0\",\"e\":\"AQAB\"}" tara_rant_identifier: 'identifier' tara_rant_secret: 'secret' diff --git a/config/initializers/aws_ses.rb b/config/initializers/aws_ses.rb new file mode 100644 index 000000000..baa148e65 --- /dev/null +++ b/config/initializers/aws_ses.rb @@ -0,0 +1,4 @@ +Aws.config.update( + region: ENV['aws_default_region'], + credentials: Aws::Credentials.new(ENV['aws_access_key_id'], ENV['aws_secret_access_key']) +) diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index f2acc88e6..4f4e68288 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,9 +1,9 @@ Rails.application.configure do config.filter_parameters += [:password, /^frame$/, /^nokogiri_frame$/, /^parsed_frame$/] config.filter_parameters << lambda do |key, value| - if key == 'raw_frame' - value.to_s.gsub!(/pw>.+<\//, 'pw>[FILTERED]]+)>([^<])+<\/eis:legalDocument>/, + if key == 'raw_frame' && value.respond_to?(:gsub!) + value.gsub!(/pw>.+<\//, 'pw>[FILTERED]]+)>([^<])+<\/eis:legalDocument>/, "[FILTERED]") end end diff --git a/config/locales/admin/domains.en.yml b/config/locales/admin/domains.en.yml index c6e96bb15..ce59294dd 100644 --- a/config/locales/admin/domains.en.yml +++ b/config/locales/admin/domains.en.yml @@ -11,6 +11,7 @@ en: search_form: reset_btn: Reset + download_csv_btn: CSV form: pending_delete: &pending_delete diff --git a/config/locales/admin/repp_logs.en.yml b/config/locales/admin/repp_logs.en.yml index 559ae234a..0a58fe7ba 100644 --- a/config/locales/admin/repp_logs.en.yml +++ b/config/locales/admin/repp_logs.en.yml @@ -4,3 +4,6 @@ en: index: title: REPP log reset_btn: Reset + show: + title: REPP log + diff --git a/config/locales/contacts.en.yml b/config/locales/contacts.en.yml index 906bde193..4b4d099d7 100644 --- a/config/locales/contacts.en.yml +++ b/config/locales/contacts.en.yml @@ -25,8 +25,10 @@ en: email_regex_check_error: Invalid format domains: exist: 'Object association prohibits operation' + delete_prohibited: Contact delete prohibited by status statuses: not_uniq: 'not uniq' + delete_prohibited: Contact delete prohibited by status country_code: invalid: Country code is not valid, should be in ISO_3166-1 alpha 2 format (%{value}) disclosed_attributes: diff --git a/config/locales/notifications.en.yml b/config/locales/notifications.en.yml index 1dff4a97c..d67fb5a5b 100644 --- a/config/locales/notifications.en.yml +++ b/config/locales/notifications.en.yml @@ -6,3 +6,5 @@ en: It was associated with registrant %{old_registrant_code} and contacts %{old_contacts_codes}. contact_update: Contact %{contact} has been updated by registrant + registrar_locked: Domain %{domain_name} has been locked by registrant + registrar_unlocked: Domain %{domain_name} has been unlocked by registrant diff --git a/config/locales/registrar/admin_contacts.en.yml b/config/locales/registrar/admin_contacts.en.yml new file mode 100644 index 000000000..9265a6d10 --- /dev/null +++ b/config/locales/registrar/admin_contacts.en.yml @@ -0,0 +1,6 @@ +en: + registrar: + admin_contacts: + update: + replaced: Admin contacts have been successfully replaced. + replaced: Technical contacts have been successfully replaced. diff --git a/config/locales/registrar/admin_contacts.yml b/config/locales/registrar/admin_contacts.yml new file mode 100644 index 000000000..d258b4275 --- /dev/null +++ b/config/locales/registrar/admin_contacts.yml @@ -0,0 +1,11 @@ +en: + registrar: + admin_contacts: + update: + replaced: Admin contacts have been successfully replaced. + affected_domains: Affected domains + skipped_domains: Skipped domains + process_request: + affected_domains: Affected domains + skipped_domains: Skipped domains + replaced: Admin contacts have been successfully replaced. diff --git a/config/locales/registrar/bulk_change.en.yml b/config/locales/registrar/bulk_change.en.yml index 75becfada..d9f6ebbd2 100644 --- a/config/locales/registrar/bulk_change.en.yml +++ b/config/locales/registrar/bulk_change.en.yml @@ -4,6 +4,7 @@ en: new: header: Bulk change technical_contact: Technical contact + admin_contact: Admin contact nameserver: Nameserver bulk_transfer: Bulk transfer bulk_renew: Bulk renew @@ -17,6 +18,19 @@ en: Replace technical contact specified in "current contact ID" with the one in "new contact ID" on any domain registered under this registrar + admin_contact_form: + current_contact_id: Current admin contact ID + new_contact_id: New admin contact ID + submit_btn: Replace admin contacts + help_btn: Toggle help + help: >- + Replace admin contact specified in "current contact ID" with the one in "new + contact ID" on any domain registered under this registrar. Contact idents must + be the same + comment: >- + Bulk admin change is only allowed in case of old and new contact are sharing identical + ident data ie for updating contact information. + nameserver_form: ip_hint: One IP per line replace_btn: Replace nameserver @@ -38,3 +52,5 @@ en: domain_ids: Domains for bulk renewal current_balance: Current balance period: Period + affected_domains: Affected domains + skipped_domains: Skipped domains diff --git a/config/locales/registrar/tech_contacts.en.yml b/config/locales/registrar/tech_contacts.en.yml index bf57f0cc7..b6e5d041b 100644 --- a/config/locales/registrar/tech_contacts.en.yml +++ b/config/locales/registrar/tech_contacts.en.yml @@ -5,3 +5,7 @@ en: replaced: Technical contacts have been successfully replaced. affected_domains: Affected domains skipped_domains: Skipped domains + process_request: + affected_domains: Affected domains + skipped_domains: Skipped domains + replaced: Technical contacts have been successfully replaced. diff --git a/config/routes.rb b/config/routes.rb index 3042eced4..949fcb345 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -64,6 +64,7 @@ Rails.application.routes.draw do get ':id/transfer_info', to: 'domains#transfer_info', constraints: { id: /.*/ } post 'transfer', to: 'domains#transfer' patch 'contacts', to: 'domains/contacts#update' + patch 'admin_contacts', to: 'domains/admin_contacts#update' post 'renew/bulk', to: 'domains/renews#bulk_renew' end end @@ -91,6 +92,7 @@ Rails.application.routes.draw do end resources :auctions, only: %i[index show update], param: :uuid + resources :contact_requests, only: %i[create update], param: :id resources :bounces, only: %i[create] end @@ -136,6 +138,7 @@ Rails.application.routes.draw do resource :bulk_change, controller: :bulk_change, only: :new post '/bulk_renew/new', to: 'bulk_change#bulk_renew', as: :bulk_renew resource :tech_contacts, only: :update + resource :admin_contacts, only: :update resource :nameservers, only: :update resources :contacts, constraints: {:id => /[^\/]+(?=#{ ActionController::Renderers::RENDERERS.map{|e| "\\.#{e}\\z"}.join("|") })|[^\/]+/} do member do @@ -188,35 +191,8 @@ Rails.application.routes.draw do end end - scope :registrant do - devise_scope :registrant_user do - get 'sign_in', to: 'registrant/sessions#new', as: :new_registrant_user_session - post 'sessions', to: 'registrant/sessions#create', as: :registrant_user_session - delete 'sign_out', to: 'registrant/sessions#destroy', as: :destroy_registrant_user_session - - # TARA - match '/open_id/callback', via: %i[get post], to: 'sso/tara#registrant_callback' - match '/open_id/cancel', via: %i[get post delete], to: 'sso/tara#cancel' - end - end - namespace :registrant do - root 'domains#index' - - # POST /registrant/sign_in is not used devise_for :users, path: '', class_name: 'RegistrantUser' - - resources :registrars, only: :show - # resources :companies, only: :index - resources :domains, only: %i[index show] do - resources :contacts, only: %i[show edit update] - member do - get 'confirmation' - end - end - - resources :domain_update_confirms, only: %i[show update] - resources :domain_delete_confirms, only: %i[show update] end # ADMIN ROUTES @@ -271,12 +247,24 @@ Rails.application.routes.draw do end end + resources :version_domain_versions do + collection do + get 'search' => 'domain_versions#search', via: [:get, :post], as: :search + end + end + resources :contact_versions do collection do get 'search' end end + resources :version_contact_versions do + collection do + get 'search' => 'contact_versions#search', via: [:get, :post], as: :search + end + end + resources :settings, only: %i[index create] resources :blocked_domains do diff --git a/db/migrate/20210215101019_add_new_balance_to_account_activity.rb b/db/migrate/20210215101019_add_new_balance_to_account_activity.rb new file mode 100644 index 000000000..64c829833 --- /dev/null +++ b/db/migrate/20210215101019_add_new_balance_to_account_activity.rb @@ -0,0 +1,5 @@ +class AddNewBalanceToAccountActivity < ActiveRecord::Migration[6.0] + def change + add_column :account_activities, :new_balance, :decimal, precision: 10, scale: 2, null: true + end +end diff --git a/db/structure.sql b/db/structure.sql index acf134a55..de2243597 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -226,7 +226,8 @@ CREATE TABLE public.account_activities ( creator_str character varying, updator_str character varying, activity_type character varying, - price_id integer + price_id integer, + new_balance numeric(10,2) ); @@ -4959,6 +4960,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20200908131554'), ('20200910085157'), ('20200910102028'), -('20200916125326'); +('20200916125326'), +('20210215101019'); diff --git a/doc/repp/v1/admin_contacts.md b/doc/repp/v1/admin_contacts.md new file mode 100644 index 000000000..3b78829d0 --- /dev/null +++ b/doc/repp/v1/admin_contacts.md @@ -0,0 +1,30 @@ +# Admin domain contacts + +## PATCH https://repp.internet.ee/v1/domains/admin_contacts +Replaces admin domain contacts of the current registrar. + +### Example request +``` +PATCH /repp/v1/domains/admin_contacts HTTP/1.1 +Accept: application/json +Content-Type: application/json +Authorization: Basic dGVzdDp0ZXN0dGVzdA== + +{ + "current_contact_id": "ATSAA:749AA80F", + "new_contact_id": "ATSAA:E36957D7" +} +``` +### Example response +``` +{ + "code": 1000, + "message": "Command completed successfully", + "data": { + "affected_domains": [ + "private.ee", + ], + "skipped_domains": [] + } +} +``` diff --git a/doc/repp/v1/domain_contacts.md b/doc/repp/v1/domain_contacts.md index 2e542bf81..8c3c9b9de 100644 --- a/doc/repp/v1/domain_contacts.md +++ b/doc/repp/v1/domain_contacts.md @@ -1,7 +1,7 @@ -# Domain contacts +# Tech domain contacts ## PATCH https://repp.internet.ee/v1/domains/contacts -Replaces all domain contacts of the current registrar. +Replaces technical domain contacts of the current registrar. ### Example request ``` diff --git a/lib/gem_monkey_patches/i18n.rb b/lib/gem_monkey_patches/i18n.rb index 2f7fceff7..7d0613247 100644 --- a/lib/gem_monkey_patches/i18n.rb +++ b/lib/gem_monkey_patches/i18n.rb @@ -5,6 +5,7 @@ module I18n alias_method :original_localize, :localize def localize(object, options = {}) + options.merge!({ default: '-' }) object.present? ? original_localize(object, options) : '' end end diff --git a/lib/serializers/registrant_api/domain.rb b/lib/serializers/registrant_api/domain.rb index 64913a7fb..b087a3a88 100644 --- a/lib/serializers/registrant_api/domain.rb +++ b/lib/serializers/registrant_api/domain.rb @@ -25,6 +25,12 @@ module Serializers registrant: { name: domain.registrant.name, id: domain.registrant.uuid, + ident: domain.registrant.ident, + ident_type: domain.registrant.ident_type, + ident_country_code: domain.registrant.ident_country_code, + phone: domain.registrant.phone, + email: domain.registrant.email, + org: domain.registrant.org?, }, tech_contacts: contacts(:tech), admin_contacts: contacts(:admin), @@ -60,7 +66,7 @@ module Serializers registrar: { name: domain.registrar.name, website: domain.registrar.website }, registrant: { name: domain.registrant.name, id: domain.registrant.uuid, phone: domain.registrant.phone, email: domain.registrant.email, - ident: domain.registrant.ident } + ident: domain.registrant.ident, org: domain.registrant.org? } } end diff --git a/lib/tasks/documents.rake b/lib/tasks/documents.rake index 5ae8fb4df..39c32a3bd 100644 --- a/lib/tasks/documents.rake +++ b/lib/tasks/documents.rake @@ -16,8 +16,8 @@ namespace :documents do next if x.documentable_id.blank? document_type = case x.documentable_type - when 'Domain' then DomainVersion - when 'Contact'then ContactVersion + when 'Domain' then Version::DomainVersion + when 'Contact'then Version::ContactVersion end dc = document_type.where(item_id: x.documentable_id) diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb index b31489691..726767390 100644 --- a/test/application_system_test_case.rb +++ b/test/application_system_test_case.rb @@ -35,7 +35,6 @@ class JavaScriptApplicationSystemTestCase < ApplicationSystemTestCase def setup DatabaseCleaner.start - super Capybara.current_driver = :chrome diff --git a/test/fixtures/contact_requests.yml b/test/fixtures/contact_requests.yml new file mode 100644 index 000000000..030a4d726 --- /dev/null +++ b/test/fixtures/contact_requests.yml @@ -0,0 +1,8 @@ +new: + whois_record_id: 1 + email: aaa@bbb.com + name: Testname + status: new + secret: somesecret + valid_to: 2010-07-05 + diff --git a/test/integration/admin_area/account_activities_test.rb b/test/integration/admin_area/account_activities_test.rb new file mode 100644 index 000000000..306935269 --- /dev/null +++ b/test/integration/admin_area/account_activities_test.rb @@ -0,0 +1,39 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaAccountActivitiesIntegrationTest < ApplicationSystemTestCase + # /admin/account_activities + setup do + sign_in users(:admin) + @original_default_language = Setting.default_language + end + + def test_show_account_activities_page + account_activities(:one).update(sum: "123.00") + visit admin_account_activities_path + assert_text 'Account activities' + end + + def test_default_url_params + account_activities(:one).update(sum: "123.00") + visit admin_root_path + click_link_or_button 'Settings', match: :first + find(:xpath, "//ul/li/a[text()='Account activities']").click + + assert has_current_path?(admin_account_activities_path(created_after: 'today')) + end + + def test_download_account_activity + now = Time.zone.parse('2010-07-05 08:00') + travel_to now + account_activities(:one).update(sum: "123.00") + + get admin_account_activities_path(format: :csv) + + assert_response :ok + assert_equal "text/csv", response.headers['Content-Type'] + assert_equal %(attachment; filename="account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv"; filename*=UTF-8''account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv), + response.headers['Content-Disposition'] + assert_not_empty response.body + end +end diff --git a/test/integration/admin_area/admin_users_test.rb b/test/integration/admin_area/admin_users_test.rb new file mode 100644 index 000000000..89b9edef9 --- /dev/null +++ b/test/integration/admin_area/admin_users_test.rb @@ -0,0 +1,101 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaAdminUsersIntegrationTest < JavaScriptApplicationSystemTestCase + include Devise::Test::IntegrationHelpers + include ActionView::Helpers::NumberHelper + + setup do + WebMock.allow_net_connect! + @original_default_language = Setting.default_language + sign_in users(:admin) + end + + def test_create_new_admin_user + createNewAdminUser(true) + end + + def test_create_with_invalid_data_new_admin_user + createNewAdminUser(false) + end + + def test_edit_successfully_exist_record + createNewAdminUser(true) + + visit admin_admin_users_path + click_on 'test_user_name' + + assert_text 'General' + click_on 'Edit' + + fill_in 'Password', with: 'test_password' + fill_in 'Password confirmation', with: 'test_password' + + click_on 'Save' + assert_text 'Record updated' + end + + def test_edit_exist_record_with_invalid_data + createNewAdminUser(true) + + visit admin_admin_users_path + click_on 'test_user_name' + + assert_text 'General' + click_on 'Edit' + + fill_in 'Password', with: 'test_password' + fill_in 'Password confirmation', with: 'test_password2' + + click_on 'Save' + assert_text 'Failed to update record' + end + + def test_delete_exist_record + createNewAdminUser(true) + + visit admin_admin_users_path + click_on 'test_user_name' + assert_text 'General' + click_on 'Delete' + + page.driver.browser.switch_to.alert.accept + + assert_text 'Record deleted' + end + + private + + def createNewAdminUser(valid) + visit admin_admin_users_path + click_on 'New admin user' + + fill_in 'Username', with: 'test_user_name' + # If valid=true creating valid user, if else, then with invalid data + if valid + fill_in 'Password', with: 'test_password' + fill_in 'Password confirmation', with: 'test_password' + else + fill_in 'Password', with: 'test_password' + fill_in 'Password confirmation', with: 'test_password2' + end + fill_in 'Identity code', with: '38903110313' + fill_in 'Email', with: 'oleg@tester.ee' + + select 'Estonia', from: 'admin_user_country_code', match: :first + + select_element = find(:xpath, "/html/body/div[2]/form/div[2]/div/div[7]/div[2]/div/div[1]") + select_element.click + + option_element = find(:xpath, "/html/body/div[2]/form/div[2]/div/div[7]/div[2]/div/div[2]/div/div[1]") + option_element.click + + click_on 'Save' + + if valid + assert_text 'Record created' + else + assert_text 'Failed to create record' + end + end +end diff --git a/test/integration/admin_area/blocked_domains_test.rb b/test/integration/admin_area/blocked_domains_test.rb new file mode 100644 index 000000000..7df9d30e7 --- /dev/null +++ b/test/integration/admin_area/blocked_domains_test.rb @@ -0,0 +1,68 @@ +require 'test_helper' +require 'application_system_test_case' + + +# /admin/blocked_domains +class AdminAreaBlockedDomainsIntegrationTest < JavaScriptApplicationSystemTestCase + setup do + WebMock.allow_net_connect! + sign_in users(:admin) + @domain = domains(:shop) + @blocked_domain = blocked_domains(:one) + end + + def test_page_successfully_loaded + visit_admin_blocked_domains_path + end + + def test_add_into_blocked_list + visit_admin_blocked_domains_path + add_domain_into_blocked_list(true) + end + + def test_add_into_blocked_list_same_domain + visit_admin_blocked_domains_path + add_domain_into_blocked_list(true) + add_domain_into_blocked_list(false) + end + + def test_delete_domain_from_blocked_list + visit_admin_blocked_domains_path + add_domain_into_blocked_list(true) + + click_link_or_button 'Delete', match: :first + + # Accept to delete in modal window + page.driver.browser.switch_to.alert.accept + + assert_text 'Domain deleted!' + end + + def test_find_blocked_domain_from_blocked_list + visit_admin_blocked_domains_path + add_domain_into_blocked_list(true) + + fill_in 'Name', with: @domain.name + find(:xpath, "//span[@class='glyphicon glyphicon-search']").click + + assert_text @domain.name + end + + private + + def visit_admin_blocked_domains_path + visit admin_blocked_domains_path + assert_text 'Blocked domains' + end + + def add_domain_into_blocked_list(value) + click_on 'New blocked domain' + assert_text 'Add domain to blocked list' + + fill_in 'Name', with: @domain.name + click_on 'Save' + + return assert_text 'Domain added!' if value + return assert_text 'Failed to add domain!' + end +end diff --git a/test/integration/admin_area/certificates_test.rb b/test/integration/admin_area/certificates_test.rb new file mode 100644 index 000000000..d2eec0bc4 --- /dev/null +++ b/test/integration/admin_area/certificates_test.rb @@ -0,0 +1,71 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaCertificatesIntegrationTest < JavaScriptApplicationSystemTestCase + + setup do + WebMock.allow_net_connect! + sign_in users(:admin) + + @apiuser = users(:api_bestnames) + @certificate = certificates(:api) + @certificate.update!(csr: "-----BEGIN CERTIFICATE REQUEST-----\nMIICszCCAZsCAQAwbjELMAkGA1UEBhMCRUUxFDASBgNVBAMMC2ZyZXNoYm94LmVl\nMRAwDgYDVQQHDAdUYWxsaW5uMREwDwYDVQQKDAhGcmVzaGJveDERMA8GA1UECAwI\nSGFyanVtYWExETAPBgNVBAsMCEZyZXNoYm94MIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEA1VVESynZoZhIbe8s9zHkELZ/ZDCGiM2Q8IIGb1IOieT5U2mx\nIsVXz85USYsSQY9+4YdEXnupq9fShArT8pstS/VN6BnxdfAiYXc3UWWAuaYAdNGJ\nDr5Jf6uMt1wVnCgoDL7eJq9tWMwARC/viT81o92fgqHFHW0wEolfCmnpik9o0ACD\nFiWZ9IBIevmFqXtq25v9CY2cT9+eZW127WtJmOY/PKJhzh0QaEYHqXTHWOLZWpnp\nHH4elyJ2CrFulOZbHPkPNB9Nf4XQjzk1ffoH6e5IVys2VV5xwcTkF0jY5XTROVxX\nlR2FWqic8Q2pIhSks48+J6o1GtXGnTxv94lSDwIDAQABoAAwDQYJKoZIhvcNAQEL\nBQADggEBAEFcYmQvcAC8773eRTWBJJNoA4kRgoXDMYiiEHih5iJPVSxfidRwYDTF\nsP+ttNTUg3JocFHY75kuM9T2USh+gu/trRF0o4WWa+AbK3JbbdjdT1xOMn7XtfUU\nZ/f1XCS9YdHQFCA6nk4Z+TLWwYsgk7n490AQOiB213fa1UIe83qIfw/3GRqRUZ7U\nwIWEGsHED5WT69GyxjyKHcqGoV7uFnqFN0sQVKVTy/NFRVQvtBUspCbsOirdDRie\nAB2KbGHL+t1QrRF10szwCJDyk5aYlVhxvdI8zn010nrxHkiyQpDFFldDMLJl10BW\n2w9PGO061z+tntdRcKQGuEpnIr9U5Vs=\n-----END CERTIFICATE REQUEST-----\n") + end + + def test_show_certificate_info + show_certificate_info + end + + def test_destroy_certificate + show_certificate_info + find(:xpath, "//a[text()='Delete']").click + + page.driver.browser.switch_to.alert.accept + + assert_text 'Record deleted' + end + + def test_download_csr + get download_csr_admin_api_user_certificate_path(api_user_id: @apiuser.id, id: @certificate.id) + + assert_response :ok + assert_equal 'application/octet-stream', response.headers['Content-Type'] + assert_equal "attachment; filename=\"test_bestnames.csr.pem\"; filename*=UTF-8''test_bestnames.csr.pem", response.headers['Content-Disposition'] + assert_not_empty response.body + end + + def test_download_crt + get download_crt_admin_api_user_certificate_path(api_user_id: @apiuser.id, id: @certificate.id) + + assert_response :ok + assert_equal 'application/octet-stream', response.headers['Content-Type'] + assert_equal "attachment; filename=\"test_bestnames.crt.pem\"; filename*=UTF-8''test_bestnames.crt.pem", response.headers['Content-Disposition'] + assert_not_empty response.body + end + + def test_failed_to_revoke_certificate + show_certificate_info + + find(:xpath, "//a[text()='Revoke this certificate']").click + assert_text 'Failed to update record' + end + + def test_new_api_user + visit new_admin_registrar_api_user_path(registrar_id: registrars(:bestnames).id) + + fill_in 'Username', with: 'testapiuser' + fill_in 'Password', with: 'secretpassword' + fill_in 'Identity code', with: '60305062718' + + click_on 'Create API user' + + assert_text 'API user has been successfully created' + end + + private + + def show_certificate_info + visit admin_api_user_certificate_path(api_user_id: @apiuser.id, id: @certificate.id) + assert_text 'Certificates' + end +end diff --git a/test/integration/admin_area/epp_logs_test.rb b/test/integration/admin_area/epp_logs_test.rb new file mode 100644 index 000000000..5ad514cb8 --- /dev/null +++ b/test/integration/admin_area/epp_logs_test.rb @@ -0,0 +1,52 @@ +# admin_epp_logs_path +require 'test_helper' +require 'application_system_test_case' + +class AdminEppLogsIntegrationTest < ApplicationSystemTestCase + setup do + sign_in users(:admin) + end + + def test_visit_epp_logs_page + visit admin_epp_logs_path + assert_text 'EPP log' + end + + def test_show_epp_log_page + visit admin_epp_logs_path + send_epp_request_hello + visit admin_epp_logs_path + + find(:xpath, "//tbody/tr/td/a", match: :first).click + assert_text 'Details' + end + + def test_dates_sort + Capybara.exact = true + visit admin_epp_logs_path + send_epp_request_hello + visit admin_epp_logs_path + + find(:xpath, "//a[contains(text(), 'Created at')]", match: :first).click + find(:xpath, "//a[contains(text(), 'Created at')]", match: :first).click + + epp_log_date = find(:xpath, "//table/tbody/tr/td[6]", match: :first).text(:all) + date_now = Date.today.to_s(:db) + + assert_match /#{date_now}/, epp_log_date + end + + private + + def send_epp_request_hello + request_xml = <<-XML + + + + + XML + + get epp_hello_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=non-existent' } + end +end diff --git a/test/integration/admin_area/invoices_test.rb b/test/integration/admin_area/invoices_test.rb index 887f57212..2aa17201d 100644 --- a/test/integration/admin_area/invoices_test.rb +++ b/test/integration/admin_area/invoices_test.rb @@ -6,6 +6,27 @@ class AdminAreaInvoicesIntegrationTest < ApplicationIntegrationTest sign_in users(:admin) end + def test_create_new_invoice + visit new_admin_invoice_path + + assert_text 'Create new invoice' + select 'Best Names', from: 'deposit_registrar_id', match: :first + fill_in 'Amount', with: '1000' + click_on 'Save' + + assert_equal page.status_code, 200 + end + + def test_visit_list_of_invoices_pages + visit admin_invoices_path + assert_text 'Invoices' + end + + def test_visit_invoice_page + visit admin_invoices_path(id: @invoice.id) + assert_text "Invoice no. #{@invoice.number}" + end + def test_downloads_invoice assert_equal 1, @invoice.number diff --git a/test/integration/admin_area/pending_delete_test.rb b/test/integration/admin_area/pending_delete_test.rb new file mode 100644 index 000000000..737d12480 --- /dev/null +++ b/test/integration/admin_area/pending_delete_test.rb @@ -0,0 +1,60 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaPendingDeleteIntegrationTest < JavaScriptApplicationSystemTestCase + setup do + WebMock.allow_net_connect! + sign_in users(:admin) + + @domain = domains(:shop) + @token = '123456' + + @domain.update!(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION], + registrant_verification_asked_at: Time.zone.now - 1.day, + registrant_verification_token: @token) + end + + def test_accept_pending_delete + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Accept' + page.driver.browser.switch_to.alert.accept + + assert_text 'Pending was successfully applied.' + end + + def test_accept_pending_delete_no_success + @domain.update!(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION], + registrant_verification_asked_at: Time.zone.now - 1.day, + registrant_verification_token: nil) + + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Accept' + page.driver.browser.switch_to.alert.accept + + assert_text 'Not success' + end + + def test_reject_panding_delete + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Reject' + page.driver.browser.switch_to.alert.accept + + assert_text 'Pending was successfully removed.' + end + + def test_accept_pending_delete_no_success + @domain.update!(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION], + registrant_verification_asked_at: Time.zone.now - 1.day, + registrant_verification_token: nil) + + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Reject' + page.driver.browser.switch_to.alert.accept + + assert_text 'Not success' + end +end diff --git a/test/integration/admin_area/pending_update_test.rb b/test/integration/admin_area/pending_update_test.rb new file mode 100644 index 000000000..5d08e104b --- /dev/null +++ b/test/integration/admin_area/pending_update_test.rb @@ -0,0 +1,96 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaPendingUpdateIntegrationTest < JavaScriptApplicationSystemTestCase + + setup do + WebMock.allow_net_connect! + sign_in users(:admin) + + @domain = domains(:hospital) + + @new_registrant = contacts(:jack) + @user = users(:api_bestnames) + @token = '123456' + + @domain.update!(statuses: [DomainStatus::PENDING_UPDATE], + registrant_verification_asked_at: Time.zone.now - 1.day, + registrant_verification_token: @token) + end + + def test_accept_pending_update + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id } + + @domain.update(pending_json: pending_json) + @domain.reload + + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Accept' + page.driver.browser.switch_to.alert.accept + + assert_text 'Pending was successfully applied.' + end + + def test_accept_pending_update_no_success + @domain.update!(statuses: [DomainStatus::PENDING_UPDATE], + registrant_verification_asked_at: Time.zone.now - 1.day, + registrant_verification_token: nil) + + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id, + } + + @domain.update(pending_json: pending_json) + @domain.reload + + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Accept' + page.driver.browser.switch_to.alert.accept + assert_text 'Not success' + end + + def test_reject_panding_update + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id, + } + + @domain.update(pending_json: pending_json) + @domain.reload + + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Reject' + page.driver.browser.switch_to.alert.accept + assert_text 'Pending was successfully removed.' + end + + def test_accept_pending_update_no_success + @domain.update!(statuses: [DomainStatus::PENDING_UPDATE], + registrant_verification_asked_at: Time.zone.now - 1.day, + registrant_verification_token: nil) + + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id, + } + + @domain.update(pending_json: pending_json) + @domain.reload + + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Reject' + page.driver.browser.switch_to.alert.accept + assert_text 'Not success' + end +end diff --git a/test/integration/admin_area/registrars_test.rb b/test/integration/admin_area/registrars_test.rb index d73496899..552650791 100644 --- a/test/integration/admin_area/registrars_test.rb +++ b/test/integration/admin_area/registrars_test.rb @@ -17,4 +17,4 @@ class AdminAreaRegistrarsIntegrationTest < ActionDispatch::IntegrationTest assert_equal new_iban, @registrar.iban end -end \ No newline at end of file +end diff --git a/test/integration/admin_area/repp_logs_test.rb b/test/integration/admin_area/repp_logs_test.rb new file mode 100644 index 000000000..6630a6d57 --- /dev/null +++ b/test/integration/admin_area/repp_logs_test.rb @@ -0,0 +1,23 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaReppLogsIntegrationTest < ApplicationSystemTestCase + setup do + sign_in users(:admin) + end + + def test_repp_logs_page + visit admin_repp_logs_path + assert_text 'REPP log' + end + + def test_show_repp_log_page + visit admin_repp_logs_path + get repp_v1_contacts_path + visit admin_repp_logs_path + + find(:xpath, "//tbody/tr/td/a", match: :first).click + + assert_text 'REPP log' + end +end diff --git a/test/integration/admin_area/reserved_domains_test.rb b/test/integration/admin_area/reserved_domains_test.rb new file mode 100644 index 000000000..c09c3723b --- /dev/null +++ b/test/integration/admin_area/reserved_domains_test.rb @@ -0,0 +1,39 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaReservedDomainsIntegrationTest < JavaScriptApplicationSystemTestCase + + setup do + WebMock.allow_net_connect! + @original_default_language = Setting.default_language + sign_in users(:admin) + + @reserved_domain = reserved_domains(:one) + end + + def test_remove_reserved_domain + visit admin_reserved_domains_path + click_link_or_button 'Delete', match: :first + page.driver.browser.switch_to.alert.accept + + assert_text 'Domain deleted!' + end + + def test_add_invalid_domain + visit admin_reserved_domains_path + click_on 'New reserved domain' + fill_in "Name", with: "@##@$" + click_on 'Save' + + assert_text 'Failed to add domain!' + end + + def test_update_reserved_domain + visit admin_reserved_domains_path + click_link_or_button 'Edit Pw', match: :first + fill_in 'Password', with: '12345678' + click_on 'Save' + + assert_text 'Domain updated!' + end +end diff --git a/test/integration/admin_area/white_ips_test.rb b/test/integration/admin_area/white_ips_test.rb new file mode 100644 index 000000000..499c86f57 --- /dev/null +++ b/test/integration/admin_area/white_ips_test.rb @@ -0,0 +1,94 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaWhiteIpsIntegrationTest < JavaScriptApplicationSystemTestCase + + setup do + WebMock.allow_net_connect! + sign_in users(:admin) + + @registrar = registrars(:bestnames) + @white_ip = white_ips(:one) + end + + def test_visit_new_whitelisted_ip_page + visit_new_whitelisted_ip_page + end + + def test_create_new_whitelisted_ip + visit_new_whitelisted_ip_page + fill_in 'IPv4', with: "127.0.0.1" + fill_in 'IPv6', with: "::ffff:192.0.2.1" + + find(:css, "#white_ip_interfaces_api").set(true) + find(:css, "#white_ip_interfaces_registrar").set(true) + + click_on 'Save' + + assert_text 'Record created' + end + + def test_failed_to_create_new_whitelisted_ip + visit_new_whitelisted_ip_page + fill_in 'IPv4', with: "asdadadad.asd" + + click_on 'Save' + + assert_text 'Failed to create record' + end + + def test_visit_edit_whitelisted_ip_page + visit_edit_whitelisted_ip_page + end + + def test_update_whitelisted_ip + visit_info_whitelisted_ip_page + click_on 'Edit' + + fill_in 'IPv4', with: "127.0.0.2" + find(:css, "#white_ip_interfaces_api").set(false) + click_on 'Save' + + assert_text 'Record updated' + end + + def test_failed_to_update_whitelisted_ip + visit_info_whitelisted_ip_page + click_on 'Edit' + fill_in 'IPv4', with: "asdadad#" + + click_on 'Save' + + assert_text 'Failed to update record' + end + + def test_visit_info_whitelisted_ip_page + visit_info_whitelisted_ip_page + end + + def test_delete_whitelisted_ip + visit_info_whitelisted_ip_page + click_on 'Delete' + + page.driver.browser.switch_to.alert.accept + + assert_text 'Record deleted' + end + + private + + def visit_new_whitelisted_ip_page + visit new_admin_registrar_white_ip_path(registrar_id: @registrar.id) + assert_text 'New whitelisted IP' + end + + def visit_edit_whitelisted_ip_page + visit edit_admin_registrar_white_ip_path(registrar_id: @registrar.id, id: @white_ip.id) + assert_text 'Edit white IP' + end + + def visit_info_whitelisted_ip_page + visit admin_registrar_white_ip_path(registrar_id: @registrar.id, id: @white_ip.id) + assert_text 'White IP' + end +end diff --git a/test/integration/api/domain_admin_contacts_test.rb b/test/integration/api/domain_admin_contacts_test.rb new file mode 100644 index 000000000..cd5b92865 --- /dev/null +++ b/test/integration/api/domain_admin_contacts_test.rb @@ -0,0 +1,153 @@ +require 'test_helper' + +class APIDomainAdminContactsTest < ApplicationIntegrationTest + setup do + @admin_current = domains(:shop).admin_contacts.find_by(code: 'jane-001') + domain = domains(:airport) + domain.admin_contacts << @admin_current + @admin_new = contacts(:william) + + @admin_new.update(ident: @admin_current.ident, + ident_type: @admin_current.ident_type, + ident_country_code: @admin_current.ident_country_code) + end + + def test_replace_all_admin_contacts_when_ident_data_doesnt_match + @admin_new.update(ident: '777' , + ident_type: 'priv', + ident_country_code: 'LV') + + patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code, + new_contact_id: @admin_new.code }, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + + assert_response :bad_request + assert_equal ({ code: 2304, message: 'Admin contacts must be identical', data: {} }), + JSON.parse(response.body, symbolize_names: true) + end + + def test_replace_all_admin_contacts_of_the_current_registrar + assert @admin_new.identical_to?(@admin_current) + patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code, + new_contact_id: @admin_new.code }, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + + assert_nil domains(:shop).admin_contacts.find_by(code: @admin_current.code) + assert domains(:shop).admin_contacts.find_by(code: @admin_new.code) + assert domains(:airport).admin_contacts.find_by(code: @admin_new.code) + end + + def test_skip_discarded_domains + domains(:airport).update!(statuses: [DomainStatus::DELETE_CANDIDATE]) + + patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code, + new_contact_id: @admin_new.code }, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + + assert domains(:airport).admin_contacts.find_by(code: @admin_current.code) + end + + def test_return_affected_domains_in_alphabetical_order + domain = domains(:airport) + domain.admin_contacts = [@admin_current] + patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code, + new_contact_id: @admin_new.code }, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + + assert_response :ok + assert_equal ({ code: 1000, message: 'Command completed successfully', data: { affected_domains: %w[airport.test shop.test], + skipped_domains: [] }}), + JSON.parse(response.body, symbolize_names: true) + end + + def test_return_skipped_domains_in_alphabetical_order + domains(:shop).update!(statuses: [DomainStatus::DELETE_CANDIDATE]) + domains(:airport).update!(statuses: [DomainStatus::DELETE_CANDIDATE]) + + patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code, + new_contact_id: @admin_new.code }, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + + assert_response :ok + assert_equal %w[airport.test shop.test], JSON.parse(response.body, + symbolize_names: true)[:data][:skipped_domains] + end + + def test_keep_other_admin_contacts_intact + patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code, + new_contact_id: @admin_new.code }, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + + assert domains(:airport).admin_contacts.find_by(code: 'john-001') + end + + def test_keep_tech_contacts_intact + patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code, + new_contact_id: @admin_new.code }, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + + assert domains(:airport).tech_contacts.find_by(code: 'william-001') + end + + def test_restrict_contacts_to_the_current_registrar + patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code, + new_contact_id: 'william-002' }, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + + assert_response :not_found + assert_equal ({ code: 2303, message: 'Object does not exist' }), + JSON.parse(response.body, symbolize_names: true) + end + + def test_non_existent_current_contact + patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: 'non-existent', + new_contact_id: @admin_new.code}, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + assert_response :not_found + assert_equal ({ code: 2303, message: 'Object does not exist' }), + JSON.parse(response.body, symbolize_names: true) + end + + def test_non_existent_new_contact + patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code, + new_contact_id: 'non-existent' }, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + assert_response :not_found + assert_equal ({code: 2303, message: 'Object does not exist'}), + JSON.parse(response.body, symbolize_names: true) + end + + def test_disallow_invalid_new_contact + patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code, + new_contact_id: 'invalid' }, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + assert_response :bad_request + assert_equal ({ code: 2304, message: 'New contact must be valid', data: {} }), + JSON.parse(response.body, symbolize_names: true) + end + + def test_admin_bulk_changed_when_domain_update_prohibited + domains(:shop).update!(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED]) + domains(:airport).admin_contacts = [@admin_current] + + shop_admin_contact = Contact.find_by(code: 'jane-001') + assert domains(:shop).admin_contacts.include?(shop_admin_contact) + + patch '/repp/v1/domains/admin_contacts', params: { current_contact_id: @admin_current.code, + new_contact_id: @admin_new.code }, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + + assert_response :ok + assert_equal ({ code: 1000, + message: 'Command completed successfully', + data: { affected_domains: ["airport.test"], + skipped_domains: ["shop.test"] }}), + JSON.parse(response.body, symbolize_names: true) + end + + private + + def http_auth_key + ActionController::HttpAuthentication::Basic.encode_credentials('test_bestnames', 'testtest') + end +end diff --git a/test/integration/api/domain_contacts_test.rb b/test/integration/api/domain_contacts_test.rb index 6704739d1..efd7032b4 100644 --- a/test/integration/api/domain_contacts_test.rb +++ b/test/integration/api/domain_contacts_test.rb @@ -107,6 +107,24 @@ class APIDomainContactsTest < ApplicationIntegrationTest JSON.parse(response.body, symbolize_names: true) end + def test_tech_bulk_changed_when_domain_update_prohibited + domains(:shop).update!(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED]) + + shop_tech_contact = Contact.find_by(code: 'william-001') + assert domains(:shop).tech_contacts.include?(shop_tech_contact) + + patch '/repp/v1/domains/contacts', params: { current_contact_id: 'william-001', + new_contact_id: 'john-001' }, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + + assert_response :ok + assert_equal ({ code: 1000, + message: 'Command completed successfully', + data: { affected_domains: ["airport.test"], + skipped_domains: ["shop.test"] }}), + JSON.parse(response.body, symbolize_names: true) + end + private def http_auth_key diff --git a/test/integration/api/domain_transfers_test.rb b/test/integration/api/domain_transfers_test.rb index 3e9c10100..3ed5b0fc6 100644 --- a/test/integration/api/domain_transfers_test.rb +++ b/test/integration/api/domain_transfers_test.rb @@ -63,6 +63,23 @@ class APIDomainTransfersTest < ApplicationIntegrationTest assert_equal 1, @new_registrar.contacts.where(name: 'William').size end + def test_bulk_transfer_if_domain_has_update_prohibited_status + domains(:shop).update!(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED]) + + post '/repp/v1/domains/transfer', params: request_params, as: :json, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + + assert_response :ok + assert_equal ({ code: 1000, + message: 'Command completed successfully', + data: { success: [], + failed: [{ type: "domain_transfer", + domain_name: "shop.test", + errors: [{:code=>"2304", :msg=>"Object status prohibits operation"}] }], + }}), + JSON.parse(response.body, symbolize_names: true) + end + private def request_params diff --git a/test/integration/api/nameservers/put_test.rb b/test/integration/api/nameservers/put_test.rb index 77b01a9b1..a55014709 100644 --- a/test/integration/api/nameservers/put_test.rb +++ b/test/integration/api/nameservers/put_test.rb @@ -104,6 +104,25 @@ class APINameserversPutTest < ApplicationIntegrationTest JSON.parse(response.body, symbolize_names: true) end + def test_bulk_namesaervers_if_domain_update_prohibited + domains(:shop).update!(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED]) + + params = { data: { type: 'nameserver', id: domains(:shop).nameservers.hostnames[0], + attributes: { hostname: 'ns55.bestnames.test' } } } + put '/repp/v1/registrar/nameservers', params: params, as: :json, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + + assert_response :ok + assert_equal ({ code: 1000, + message: 'Command completed successfully', + data: { type: "nameserver", + id: "ns55.bestnames.test", + attributes: {hostname: "ns55.bestnames.test"}, + affected_domains: ["airport.test"], + skipped_domains: ["shop.test"]}}), + JSON.parse(response.body, symbolize_names: true) + end + def test_unauthenticated put '/repp/v1/registrar/nameservers' assert_response 401 diff --git a/test/integration/api/registrant/registrant_api_contacts_test.rb b/test/integration/api/registrant/registrant_api_contacts_test.rb index 191222764..f3998a2e9 100644 --- a/test/integration/api/registrant/registrant_api_contacts_test.rb +++ b/test/integration/api/registrant/registrant_api_contacts_test.rb @@ -57,6 +57,15 @@ class RegistrantApiContactsTest < ApplicationIntegrationTest assert_equal({ errors: [base: ['Not authorized']] }, json_body) end + def test_gets_contact_domain_links_when_requested + get "/api/v1/registrant/contacts/#{@contact.uuid}?links=true", headers: @auth_headers + + expected_links = @contact.domains.uniq.map { |d| { name: d.name, id: d.uuid }} + assert_response :ok + response_json = JSON.parse(response.body, symbolize_names: true) + + assert_empty expected_links - response_json[:links] + end private def auth_token diff --git a/test/integration/api/registrant/registrant_api_domains_test.rb b/test/integration/api/registrant/registrant_api_domains_test.rb index 61d635e5f..a8801f1b4 100644 --- a/test/integration/api/registrant/registrant_api_domains_test.rb +++ b/test/integration/api/registrant/registrant_api_domains_test.rb @@ -5,9 +5,10 @@ class RegistrantApiDomainsTest < ApplicationIntegrationTest def setup super - @domain = domains(:hospital) + @domain = domains(:airport) @registrant = @domain.registrant @user = users(:registrant) + domains(:metro).tech_domain_contacts.update(contact_id: @registrant.id) @auth_headers = { 'HTTP_AUTHORIZATION' => auth_token } end @@ -19,7 +20,14 @@ class RegistrantApiDomainsTest < ApplicationIntegrationTest assert_equal('hospital.test', domain[:name]) assert_equal('5edda1a5-3548-41ee-8b65-6d60daf85a37', domain[:id]) - assert_equal({name: 'John', id: 'eb2f2766-b44c-4e14-9f16-32ab1a7cb957'}, domain[:registrant]) + assert_equal({:name=>"John", + :id=>"eb2f2766-b44c-4e14-9f16-32ab1a7cb957", + :ident=>"1234", :ident_type=>"priv", + :ident_country_code=>"US", + :phone=>"+555.555", + :email=>"john@inbox.test", + :org=>false}, + domain[:registrant]) assert_equal([{name: 'John', id: 'eb2f2766-b44c-4e14-9f16-32ab1a7cb957', email: 'john@inbox.test'}], @@ -57,6 +65,46 @@ class RegistrantApiDomainsTest < ApplicationIntegrationTest assert(array_of_domain_registrars.include?({name: 'Good Names', website: nil})) end + def test_return_domain_list_with_registrants_and_admins + domains(:hospital).admin_domain_contacts.update(contact_id: contacts(:william).id) + domains(:hospital).update(registrant: contacts(:william).becomes(Registrant)) + + get '/api/v1/registrant/domains', headers: @auth_headers, params: { 'offset' => 0 } + assert_equal(200, response.status) + + response_json = JSON.parse(response.body, symbolize_names: true) + response_json[:domains].each do |x| + if x[:registrant][:org] == false + x[:tech_contacts].each do |s| + assert_not s[:name].include?(@registrant.name) + end + end + end + end + + def test_return_domain_list_with_registrants_and_admins_tech + get '/api/v1/registrant/domains', headers: @auth_headers, params: { 'offset' => 0, 'tech' => true } + assert_equal(200, response.status) + + response_json = JSON.parse(response.body, symbolize_names: true) + response_json[:domains].each do |x| + if x[:name] == 'metro.test' + x[:tech_contacts].each do |s| + assert s[:name].include?(@registrant.name) + end + end + end + end + + def test_domains_total_if_an_incomplete_list_is_returned + get '/api/v1/registrant/domains', headers: @auth_headers, params: { 'offset' => 0 } + assert_equal(200, response.status) + + response_json = JSON.parse(response.body, symbolize_names: true) + assert_equal response_json[:domains].length, response_json[:count] + assert_equal response_json[:total], 5 + end + def test_root_accepts_limit_and_offset_parameters get '/api/v1/registrant/domains', params: { 'limit' => 2, 'offset' => 0 }, headers: @auth_headers diff --git a/test/integration/api/registrant/registrant_api_registry_locks_test.rb b/test/integration/api/registrant/registrant_api_registry_locks_test.rb index fb6d13aca..0de47dbc9 100644 --- a/test/integration/api/registrant/registrant_api_registry_locks_test.rb +++ b/test/integration/api/registrant/registrant_api_registry_locks_test.rb @@ -130,7 +130,15 @@ class RegistrantApiRegistryLocksTest < ApplicationIntegrationTest response_json = JSON.parse(response.body, symbolize_names: true) assert_equal({ name: 'Best Names', website: 'https://bestnames.test' }, response_json[:registrar]) - assert_equal({name: 'John', id: 'eb2f2766-b44c-4e14-9f16-32ab1a7cb957'}, response_json[:registrant]) + assert_equal({:name=>"John", + :id=>"eb2f2766-b44c-4e14-9f16-32ab1a7cb957", + :ident=>"1234", + :ident_type=>"priv", + :ident_country_code=>"US", + :phone=>"+555.555", + :email=>"john@inbox.test", + :org=>false}, + response_json[:registrant]) assert_equal([{name: 'Jane', id: '9db3de62-2414-4487-bee2-d5c155567768', email: 'jane@mail.test' diff --git a/test/integration/api/v1/bounces/create_test.rb b/test/integration/api/v1/bounces/create_test.rb index 899b6c5c7..0d3dc65d7 100644 --- a/test/integration/api/v1/bounces/create_test.rb +++ b/test/integration/api/v1/bounces/create_test.rb @@ -2,7 +2,7 @@ require 'test_helper' class BouncesApiV1CreateTest < ActionDispatch::IntegrationTest def setup - @api_key = "Basic #{ENV['api_shared_key']}" + @api_key = "Basic #{ENV['rwhois_bounces_api_shared_key']}" @headers = { "Authorization": "#{@api_key}" } @json_body = { "data": valid_bounce_request }.as_json end diff --git a/test/integration/api/v1/contact_requests_test.rb b/test/integration/api/v1/contact_requests_test.rb new file mode 100644 index 000000000..c9e2ac9bd --- /dev/null +++ b/test/integration/api/v1/contact_requests_test.rb @@ -0,0 +1,68 @@ +require 'test_helper' + +class ApiV1ContactRequestTest < ActionDispatch::IntegrationTest + def setup + @api_key = "Basic #{ENV['rwhois_internal_api_shared_key']}" + @headers = { "Authorization": "#{@api_key}" } + @json_create = { "contact_request": valid_contact_request_create }.as_json + @json_update = { "contact_request": valid_contact_request_update }.as_json + @contact_request = contact_requests(:new) + end + + def test_authorizes_api_request + post api_v1_contact_requests_path, params: @json_create, headers: @headers + assert_response :created + + invalid_headers = { "Authorization": "Basic invalid_api_key" } + post api_v1_contact_requests_path, params: @json_create, headers: invalid_headers + assert_response :unauthorized + end + + def test_saves_new_contact_request + request_body = @json_create.dup + random_mail = "#{rand(10000..99999)}@registry.test" + request_body['contact_request']['email'] = random_mail + + post api_v1_contact_requests_path, params: request_body, headers: @headers + assert_response :created + + contact_request = ContactRequest.last + assert_equal contact_request.email, random_mail + assert ContactRequest::STATUS_NEW, contact_request.status + end + + def test_updates_existing_contact_request + request_body = @json_update.dup + + put api_v1_contact_request_path(@contact_request.id), params: request_body, headers: @headers + assert_response :ok + + @contact_request.reload + assert ContactRequest::STATUS_CONFIRMED, @contact_request.status + end + + def test_not_updates_if_status_error + request_body = @json_update.dup + request_body['contact_request']['status'] = 'some_error_status' + + put api_v1_contact_request_path(@contact_request.id), params: request_body, headers: @headers + assert_response 400 + + @contact_request.reload + assert ContactRequest::STATUS_NEW, @contact_request.status + end + + def valid_contact_request_create + { + "email": "aaa@bbb.com", + "whois_record_id": "1", + "name": "test" + }.as_json + end + + def valid_contact_request_update + { + "status": "#{ContactRequest::STATUS_CONFIRMED}", + }.as_json + end +end diff --git a/test/integration/api/v1/registrant/contacts/list_test.rb b/test/integration/api/v1/registrant/contacts/list_test.rb index 2389019f1..33e8b67eb 100644 --- a/test/integration/api/v1/registrant/contacts/list_test.rb +++ b/test/integration/api/v1/registrant/contacts/list_test.rb @@ -1,5 +1,6 @@ require 'test_helper' require 'auth_token/auth_token_creator' +require 'json' CompanyRegisterClientStub = Struct.new(:any_method) do def representation_rights(citizen_personal_code:, citizen_country_code:) @@ -55,6 +56,42 @@ class RegistrantApiV1ContactListTest < ActionDispatch::IntegrationTest assert_equal '1234', response_json.first[:ident][:code] end + def test_out_of_range_limit + get api_v1_registrant_contacts_path + "?limit=300", as: :json, headers: { 'HTTP_AUTHORIZATION' => auth_token } + response_json = JSON.parse(response.body, symbolize_names: true) + + text_response = JSON.pretty_generate(response_json[:errors][0][:limit][0]) + + assert_equal text_response, '"parameter is out of range"' + end + + def test_negative_offset + get api_v1_registrant_contacts_path + "?offset=-300", as: :json, headers: { 'HTTP_AUTHORIZATION' => auth_token } + response_json = JSON.parse(response.body, symbolize_names: true) + + text_response = JSON.pretty_generate(response_json[:errors][0][:offset][0]) + + assert_equal text_response, '"parameter is out of range"' + end + + def test_show_valid_contact + get api_v1_registrant_contacts_path + "/eb2f2766-b44c-4e14-9f16-32ab1a7cb957", as: :json, headers: { 'HTTP_AUTHORIZATION' => auth_token } + response_json = JSON.parse(response.body, symbolize_names: true) + + text_response = response_json[:name] + + assert_equal @contact[:name], text_response + end + + def test_show_invalid_contact + get api_v1_registrant_contacts_path + "/435", as: :json, headers: { 'HTTP_AUTHORIZATION' => auth_token } + response_json = JSON.parse(response.body, symbolize_names: true) + + text_response = response_json[:errors][0][:base][0] + + assert_equal text_response, 'Contact not found' + end + private def delete_direct_contact diff --git a/test/integration/api/v1/registrant/contacts/update_test.rb b/test/integration/api/v1/registrant/contacts/update_test.rb index 4ddf8b0ff..c1eaa005c 100644 --- a/test/integration/api/v1/registrant/contacts/update_test.rb +++ b/test/integration/api/v1/registrant/contacts/update_test.rb @@ -4,11 +4,12 @@ require 'auth_token/auth_token_creator' class RegistrantApiV1ContactUpdateTest < ActionDispatch::IntegrationTest setup do @contact = contacts(:john) + @contact_org = contacts(:acme_ltd) @original_address_processing = Setting.address_processing @original_fax_enabled_setting = ENV['fax_enabled'] - @user = users(:registrant) + end teardown do @@ -90,6 +91,32 @@ class RegistrantApiV1ContactUpdateTest < ActionDispatch::IntegrationTest @contact.address end + def test_update_address_when_enabled_without_address_params + Setting.address_processing = true + + patch api_v1_registrant_contact_path(@contact.uuid), params: { address: { } }, + as: :json, + headers: { 'HTTP_AUTHORIZATION' => auth_token } + + assert_response :bad_request + @contact.reload + assert_equal Contact::Address.new(nil, nil, nil, nil, nil), + @contact.address + end + + def test_update_address_when_enabled_without_address_params + Setting.address_processing = true + + patch api_v1_registrant_contact_path(@contact.uuid), params: { }, + as: :json, + headers: { 'HTTP_AUTHORIZATION' => auth_token } + + assert_response :bad_request + @contact.reload + assert_equal Contact::Address.new(nil, nil, nil, nil, nil), + @contact.address + end + def test_address_is_optional_when_enabled Setting.address_processing = true @contact.update!(street: 'any', zip: 'any', city: 'any', state: 'any', country_code: 'US') @@ -211,6 +238,21 @@ class RegistrantApiV1ContactUpdateTest < ActionDispatch::IntegrationTest symbolize_names: true) end + def test_org_disclosed_attributes + patch api_v1_registrant_contact_path(@contact_org.uuid), params: { disclosed_attributes: ["some_attr"] }, + as: :json, + headers: { 'HTTP_AUTHORIZATION' => auth_token } + + assert_response :bad_request + + err_msg = "Legal person's data is visible by default and cannot be concealed. Please remove this parameter." + + response_json = JSON.parse(response.body, symbolize_names: true) + response_msg = response_json[:errors][0][:disclosed_attributes][0] + + assert_equal err_msg, response_msg + end + def test_unmanaged_contact_cannot_be_updated assert_equal 'US-1234', @user.registrant_ident @contact.update!(ident: '12345') diff --git a/test/integration/epp/contact/check/base_test.rb b/test/integration/epp/contact/check/base_test.rb index 528d69d86..8f7e3df16 100644 --- a/test/integration/epp/contact/check/base_test.rb +++ b/test/integration/epp/contact/check/base_test.rb @@ -26,7 +26,7 @@ class EppContactCheckBaseTest < EppTestCase response_xml = Nokogiri::XML(response.body) assert_epp_response :completed_successfully - assert_equal 'john-001', response_xml.at_xpath('//contact:id', contact: xml_schema).text + assert_equal "#{@contact.registrar.code}:JOHN-001".upcase, response_xml.at_xpath('//contact:id', contact: xml_schema).text end def test_contact_is_available @@ -52,7 +52,8 @@ class EppContactCheckBaseTest < EppTestCase end def test_contact_is_unavailable - assert_equal 'john-001', @contact.code + @contact.update_columns(code: "#{@contact.registrar.code}:JOHN-001".upcase) + assert @contact.code, "#{@contact.registrar.code}:JOHN-001".upcase request_xml = <<-XML @@ -98,9 +99,61 @@ class EppContactCheckBaseTest < EppTestCase assert_equal 3, response_xml.xpath('//contact:cd', contact: xml_schema).size end + def test_check_contact_with_prefix + @contact.update_columns(code: "#{@contact.registrar.code}:JOHN-001".upcase) + assert @contact.code, "#{@contact.registrar.code}:JOHN-001".upcase + + request_xml = <<-XML + + + + + + BESTNAMES:JOHN-001 + + + + + XML + + post epp_check_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + + response_xml = Nokogiri::XML(response.body) + assert_epp_response :completed_successfully + assert_equal "#{@contact.registrar.code}:JOHN-001".upcase, response_xml.at_xpath('//contact:id', contact: xml_schema).text + assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text + end + + def test_check_contact_without_prefix + @contact.update_columns(code: "#{@contact.registrar.code}:JOHN-001".upcase) + assert @contact.code, "#{@contact.registrar.code}:JOHN-001".upcase + + request_xml = <<-XML + + + + + + JOHN-001 + + + + + XML + + post epp_check_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + + response_xml = Nokogiri::XML(response.body) + assert_epp_response :completed_successfully + assert_equal "#{@contact.registrar.code}:JOHN-001".upcase, response_xml.at_xpath('//contact:id', contact: xml_schema).text + assert_equal 'in use', response_xml.at_xpath('//contact:reason', contact: xml_schema).text + end + private def xml_schema 'https://epp.tld.ee/schema/contact-ee-1.1.xsd' end -end \ No newline at end of file +end diff --git a/test/integration/epp/contact/delete/base_test.rb b/test/integration/epp/contact/delete/base_test.rb index 26ba63897..e86bea9dd 100644 --- a/test/integration/epp/contact/delete/base_test.rb +++ b/test/integration/epp/contact/delete/base_test.rb @@ -27,6 +27,60 @@ class EppContactDeleteBaseTest < EppTestCase assert_epp_response :completed_successfully end + def test_delete_contact_with_server_delete_prohibited + contact = deletable_contact + contact.update(statuses: Contact::SERVER_DELETE_PROHIBITED) + assert contact.statuses.include? Contact::SERVER_DELETE_PROHIBITED + + contact.update_columns(code: contact.code.upcase) + + request_xml = <<-XML + + + + + + #{contact.code.upcase} + + + + + XML + + post epp_delete_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + + assert Contact.exists?(id: contact.id) + assert_epp_response :object_status_prohibits_operation + end + + def test_delete_contact_with_client_delete_prohibited + contact = deletable_contact + contact.update(statuses: Contact::CLIENT_DELETE_PROHIBITED) + assert contact.statuses.include? Contact::CLIENT_DELETE_PROHIBITED + + contact.update_columns(code: contact.code.upcase) + + request_xml = <<-XML + + + + + + #{contact.code.upcase} + + + + + XML + + post epp_delete_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + + assert Contact.exists?(id: contact.id) + assert_epp_response :object_status_prohibits_operation + end + def test_undeletable_cannot_be_deleted contact = contacts(:john) assert_not contact.deletable? @@ -61,4 +115,4 @@ class EppContactDeleteBaseTest < EppTestCase DomainContact.delete_all contacts(:john) end -end \ No newline at end of file +end diff --git a/test/integration/epp/contact/info/base_test.rb b/test/integration/epp/contact/info/base_test.rb index 4e4a9190e..3edb6d461 100644 --- a/test/integration/epp/contact/info/base_test.rb +++ b/test/integration/epp/contact/info/base_test.rb @@ -44,6 +44,58 @@ class EppContactInfoBaseTest < EppTestCase contact: xml_schema).text end + def test_get_info_about_contact_with_prefix + @contact.update_columns(code: 'TEST:JOHN-001') + assert @contact.code, 'TEST:JOHN-001' + + request_xml = <<-XML + + + + + + TEST:JOHN-001 + + + + + XML + + post epp_info_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + + response_xml = Nokogiri::XML(response.body) + assert_epp_response :completed_successfully + assert_equal 'TEST:JOHN-001', response_xml.at_xpath('//contact:id', contact: xml_schema).text + assert_equal '+555.555', response_xml.at_xpath('//contact:voice', contact: xml_schema).text + end + + def test_get_info_about_contact_without_prefix + @contact.update_columns(code: "#{@contact.registrar.code}:JOHN-001".upcase) + assert @contact.code, "#{@contact.registrar.code}:JOHN-001".upcase + + request_xml = <<-XML + + + + + + JOHN-001 + + + + + XML + + post epp_info_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + + response_xml = Nokogiri::XML(response.body) + assert_epp_response :completed_successfully + assert_equal "#{@contact.registrar.code}:JOHN-001".upcase, response_xml.at_xpath('//contact:id', contact: xml_schema).text + assert_equal '+555.555', response_xml.at_xpath('//contact:voice', contact: xml_schema).text + end + def test_hides_password_and_name_when_current_registrar_is_not_sponsoring non_sponsoring_registrar = registrars(:goodnames) @contact.update!(registrar: non_sponsoring_registrar) diff --git a/test/integration/epp/domain/create/base_test.rb b/test/integration/epp/domain/create/base_test.rb index 9d817524d..35ef38179 100644 --- a/test/integration/epp/domain/create/base_test.rb +++ b/test/integration/epp/domain/create/base_test.rb @@ -2,6 +2,51 @@ require 'test_helper' class EppDomainCreateBaseTest < EppTestCase + def test_illegal_chars_in_dns_key + name = "new.#{dns_zones(:one).origin}" + contact = contacts(:john) + registrant = contact.becomes(Registrant) + + pub_key = "AwEAAddt2AkLf\n + \n + YGKgiEZB5SmIF8E\n + vrjxNMH6HtxW\rEA4RJ9Ao6LCWheg8" + + request_xml = <<-XML + + + + + + #{name} + #{registrant.code} + + + + + + 257 + 3 + 8 + #{pub_key} + + + + #{'test' * 2000} + + + + + XML + assert_no_difference 'Domain.count' do + post epp_create_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + end + + assert_epp_response :parameter_value_syntax_error + end + + def test_not_registers_domain_without_legaldoc now = Time.zone.parse('2010-07-05') travel_to now @@ -31,6 +76,230 @@ class EppDomainCreateBaseTest < EppTestCase assert_epp_response :required_parameter_missing end + def test_create_domain_with_unique_contact + now = Time.zone.parse('2010-07-05') + travel_to now + name = "new.#{dns_zones(:one).origin}" + contact = contacts(:john) + registrant = contact.becomes(Registrant) + + request_xml = <<-XML + + + + + + #{name} + #{registrant.code} + #{contacts(:jane).code} + #{contacts(:william).code} + + + + + #{'test' * 2000} + + + + + XML + + assert_difference 'Domain.count' do + post epp_create_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + end + assert_epp_response :completed_successfully + end + + + def test_create_domain_with_array_of_not_unique_admins_and_techs + now = Time.zone.parse('2010-07-05') + travel_to now + name = "new.#{dns_zones(:one).origin}" + contact = contacts(:john) + registrant = contact.becomes(Registrant) + + request_xml = <<-XML + + + + + + #{name} + #{registrant.code} + #{contact.code} + #{contact.code} + #{contact.code} + #{contact.code} + + + + + #{'test' * 2000} + + + + + XML + + assert_no_difference 'Domain.count' do + post epp_create_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + end + + assert_epp_response :parameter_value_policy_error + end + + def test_create_domain_with_array_of_not_unique_admins + now = Time.zone.parse('2010-07-05') + travel_to now + name = "new.#{dns_zones(:one).origin}" + contact = contacts(:john) + registrant = contact.becomes(Registrant) + + request_xml = <<-XML + + + + + + #{name} + #{registrant.code} + #{contact.code} + #{contact.code} + #{contact.code} + + + + + #{'test' * 2000} + + + + + XML + + assert_no_difference 'Domain.count' do + post epp_create_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + end + + assert_epp_response :parameter_value_policy_error + end + + def test_create_domain_with_array_of_not_unique_techs + now = Time.zone.parse('2010-07-05') + travel_to now + name = "new.#{dns_zones(:one).origin}" + contact = contacts(:john) + registrant = contact.becomes(Registrant) + + request_xml = <<-XML + + + + + + #{name} + #{registrant.code} + #{contact.code} + #{contact.code} + #{contact.code} + + + + + #{'test' * 2000} + + + + + XML + + assert_no_difference 'Domain.count' do + post epp_create_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + end + + assert_epp_response :parameter_value_policy_error + end + + def test_create_domain_with_array_of_not_unique_admin_but_tech_another_one + now = Time.zone.parse('2010-07-05') + travel_to now + name = "new.#{dns_zones(:one).origin}" + contact = contacts(:john) + registrant = contact.becomes(Registrant) + contact_two = contacts(:william) + + request_xml = <<-XML + + + + + + #{name} + #{registrant.code} + #{contact.code} + #{contact.code} + #{contact_two.code} + + + + + #{'test' * 2000} + + + + + XML + + assert_no_difference 'Domain.count' do + post epp_create_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + end + + assert_epp_response :parameter_value_policy_error + end + + def test_create_domain_with_array_of_not_unique_techs_but_admin_another_one + now = Time.zone.parse('2010-07-05') + travel_to now + name = "new.#{dns_zones(:one).origin}" + contact = contacts(:john) + registrant = contact.becomes(Registrant) + contact_two = contacts(:william) + + request_xml = <<-XML + + + + + + #{name} + #{registrant.code} + #{contact_two.code} + #{contact.code} + #{contact.code} + + + + + #{'test' * 2000} + + + + + XML + + assert_no_difference 'Domain.count' do + post epp_create_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + end + + assert_epp_response :parameter_value_policy_error + end + def test_registers_new_domain_with_required_attributes now = Time.zone.parse('2010-07-05') travel_to now diff --git a/test/integration/epp/domain/delete/base_test.rb b/test/integration/epp/domain/delete/base_test.rb index 56a3cc31e..d32a89f63 100644 --- a/test/integration/epp/domain/delete/base_test.rb +++ b/test/integration/epp/domain/delete/base_test.rb @@ -133,6 +133,40 @@ class EppDomainDeleteBaseTest < EppTestCase assert_epp_response :completed_successfully end + def test_deletes_on_update_prohibited + assert_equal 'shop.test', @domain.name + @domain.update(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED]) + Setting.request_confirmation_on_domain_deletion_enabled = false + + request_xml = <<-XML + + + + + + shop.test + + + + + #{'test' * 2000} + + + + + XML + + perform_enqueued_jobs do + post epp_delete_path, params: { frame: request_xml }, headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + end + @domain.reload + + assert_not @domain.registrant_verification_asked? + assert_not @domain.pending_delete_confirmation? + assert_no_emails + assert_epp_response :completed_successfully + end + def test_skips_registrant_confirmation_when_required_but_already_verified_by_registrar assert_equal 'shop.test', @domain.name Setting.request_confirmation_on_domain_deletion_enabled = true diff --git a/test/integration/epp/domain/transfer/request_test.rb b/test/integration/epp/domain/transfer/request_test.rb index 1c3614421..273a9f490 100644 --- a/test/integration/epp/domain/transfer/request_test.rb +++ b/test/integration/epp/domain/transfer/request_test.rb @@ -3,6 +3,7 @@ require 'test_helper' class EppDomainTransferRequestTest < EppTestCase def setup @domain = domains(:shop) + @contact = contacts(:jane) @new_registrar = registrars(:goodnames) @original_transfer_wait_time = Setting.transfer_wait_time Setting.transfer_wait_time = 0 @@ -12,6 +13,95 @@ class EppDomainTransferRequestTest < EppTestCase Setting.transfer_wait_time = @original_transfer_wait_time end + def test_transfer_domain_with_contacts_if_registrant_and_tech_are_shared + @domain.tech_domain_contacts[0].update!(contact_id: @domain.registrant.id) + + @domain.tech_domain_contacts[1].delete + @domain.reload + + post epp_transfer_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_goodnames' } + + assert_epp_response :completed_successfully + + @domain.reload + + tech = Contact.find_by(id: @domain.tech_domain_contacts[0].contact_id) + + assert_equal @domain.contacts.where(original_id: @domain.registrant.original_id).count, 1 + assert_equal tech.registrar_id, @domain.registrar.id + end + + def test_transfer_domain_with_contacts_if_registrant_and_admin_are_shared + @domain.admin_domain_contacts[0].update!(contact_id: @domain.registrant.id) + @domain.tech_domain_contacts[0].update!(contact_id: @contact.id) + + @domain.tech_domain_contacts[1].delete + @domain.reload + + post epp_transfer_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_goodnames' } + + assert_epp_response :completed_successfully + + @domain.reload + + admin = Contact.find_by(id: @domain.admin_domain_contacts[0].contact_id) + + assert_equal @domain.contacts.where(original_id: @domain.registrant.original_id).count, 1 + assert_equal admin.registrar_id, @domain.registrar.id + end + + def test_transfer_domain_with_contacts_if_admin_and_tech_are_shared + @domain.admin_domain_contacts[0].update!(contact_id: @contact.id) + @domain.tech_domain_contacts[0].update!(contact_id: @contact.id) + + @domain.tech_domain_contacts[1].delete + @domain.reload + + post epp_transfer_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_goodnames' } + + assert_epp_response :completed_successfully + + @domain.reload + + admin = Contact.find_by(id: @domain.admin_domain_contacts[0].contact_id) + tech = Contact.find_by(id: @domain.tech_domain_contacts[0].contact_id) + + result_hash = @domain.contacts.pluck(:original_id).group_by(&:itself).transform_values(&:count) + assert result_hash[admin.original_id], 2 + + assert_equal admin.registrar_id, @domain.registrar.id + assert_equal tech.registrar_id, @domain.registrar.id + end + + def test_transfer_domain_with_contacts_if_admin_and_tech_and_registrant_are_shared + @domain.tech_domain_contacts[0].update!(contact_id: @domain.registrant.id) + @domain.admin_domain_contacts[0].update!(contact_id: @domain.registrant.id) + + @domain.tech_domain_contacts[1].delete + @domain.reload + + post epp_transfer_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_goodnames' } + + assert_epp_response :completed_successfully + + @domain.reload + + admin = Contact.find_by(id: @domain.admin_domain_contacts[0].contact_id) + tech = Contact.find_by(id: @domain.tech_domain_contacts[0].contact_id) + + assert_equal @domain.contacts.where(original_id: @domain.registrant.original_id).count, 2 + + result_hash = @domain.contacts.pluck(:original_id).group_by(&:itself).transform_values(&:count) + assert result_hash[@domain.registrant.original_id], 2 + + assert_equal admin.registrar_id, @domain.registrar.id + assert_equal tech.registrar_id, @domain.registrar.id + end + def test_transfers_domain_at_once post epp_transfer_path, params: { frame: request_xml }, headers: { 'HTTP_COOKIE' => 'session=api_goodnames' } diff --git a/test/integration/epp/domain/update/base_test.rb b/test/integration/epp/domain/update/base_test.rb index 7ddcb35ad..83ba65478 100644 --- a/test/integration/epp/domain/update/base_test.rb +++ b/test/integration/epp/domain/update/base_test.rb @@ -63,6 +63,27 @@ class EppDomainUpdateBaseTest < EppTestCase assert_epp_response :object_status_prohibits_operation end + def test_prohibited_domain_cannot_be_updated + @domain.update!(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED]) + + request_xml = <<-XML + + + + + + shop.test + + + + + XML + + post epp_update_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + assert_epp_response :object_status_prohibits_operation + end + def test_does_not_return_server_delete_prohibited_status_when_pending_update_status_is_set @domain.update!(statuses: [DomainStatus::SERVER_DELETE_PROHIBITED, DomainStatus::PENDING_UPDATE]) @@ -124,6 +145,46 @@ class EppDomainUpdateBaseTest < EppTestCase assert_verification_and_notification_emails end + def test_domain_should_doesnt_have_pending_update_when_updated_registrant_with_same_idents_data + assert_not @domain.statuses.include? "pendingUpdate" + + old_registrant = @domain.registrant + new_registrant = contacts(:william).becomes(Registrant) + + new_registrant.update(ident: old_registrant.ident) + new_registrant.update(ident_country_code: old_registrant.ident_country_code) + new_registrant.update(ident_type: old_registrant.ident_type) + + request_xml = <<-XML + + + + + + #{@domain.name} + + #{new_registrant.code} + + + + + + #{'test' * 2000} + + + + + XML + + post epp_update_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + @domain.reload + assert_epp_response :completed_successfully + + assert_equal @domain.registrant, new_registrant + assert_not @domain.statuses.include? "pendingUpdate" + end + def test_requires_verification_from_current_registrant_when_not_yet_verified_by_registrar Setting.request_confirmation_on_registrant_change_enabled = true new_registrant = contacts(:william) diff --git a/test/integration/epp/poll_test.rb b/test/integration/epp/poll_test.rb index 6d3ec467e..a18fdbe4e 100644 --- a/test/integration/epp/poll_test.rb +++ b/test/integration/epp/poll_test.rb @@ -26,6 +26,31 @@ class EppPollTest < EppTestCase assert_equal 'Your domain has been updated', xml_doc.at_css('msgQ msg').text end + def test_does_not_drop_error_if_old_version + version = Version::DomainVersion.last + @notification.update(attached_obj_type: 'DomainVersion', attached_obj_id: version.id) + + request_xml = <<-XML + + + + + + + XML + assert_nothing_raised do + post epp_poll_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + end + + xml_doc = Nokogiri::XML(response.body) + assert_epp_response :completed_successfully_ack_to_dequeue + assert_equal 2.to_s, xml_doc.at_css('msgQ')[:count] + assert_equal @notification.id.to_s, xml_doc.at_css('msgQ')[:id] + assert_equal Time.zone.parse('2010-07-05').utc.xmlschema, xml_doc.at_css('msgQ qDate').text + assert_equal 'Your domain has been updated', xml_doc.at_css('msgQ msg').text + end + def test_return_action_data_when_present @notification.update!(action: actions(:contact_update)) diff --git a/test/integration/registrant_area/contacts_test.rb b/test/integration/registrant_area/contacts_test.rb deleted file mode 100644 index c906cd026..000000000 --- a/test/integration/registrant_area/contacts_test.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'test_helper' - -class RegistrantAreaContactsIntegrationTest < ApplicationIntegrationTest - setup do - @domain = domains(:shop) - @registrant = users(:registrant) - sign_in @registrant - end - - def test_can_view_other_domain_contacts - secondary_contact = contacts(:jane) - - visit registrant_domain_path(@domain) - assert_text secondary_contact.name - click_link secondary_contact.name - assert_text @domain.name - assert_text secondary_contact.email - end -end diff --git a/test/integration/registrant_area/domain_delete_confirmations.rb b/test/integration/registrant_area/domain_delete_confirmations.rb deleted file mode 100644 index 29bca7ed9..000000000 --- a/test/integration/registrant_area/domain_delete_confirmations.rb +++ /dev/null @@ -1,30 +0,0 @@ -require 'test_helper' - -class RegistrantAreaDomainDeleteConfirmationIntegrationTest < ActionDispatch::IntegrationTest - include ActionMailer::TestHelper - - setup do - @domain = domains(:shop) - ActionMailer::Base.deliveries.clear - end - - def test_notifies_registrant_by_email_when_accepted - @domain.update!(registrant_verification_asked_at: Time.zone.now, - registrant_verification_token: 'test', - statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION]) - - patch registrant_domain_delete_confirm_path(@domain, token: 'test', confirmed: true) - - assert_emails 1 - end - - def test_notifies_registrant_by_email_when_rejected - @domain.update!(registrant_verification_asked_at: Time.zone.now, - registrant_verification_token: 'test', - statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION]) - - patch registrant_domain_delete_confirm_path(@domain, token: 'test', rejected: true) - - assert_emails 1 - end -end \ No newline at end of file diff --git a/test/integration/registrant_area/domains_test.rb b/test/integration/registrant_area/domains_test.rb deleted file mode 100644 index d2ca1c775..000000000 --- a/test/integration/registrant_area/domains_test.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'test_helper' - -class RegistrantAreaDomainsIntegrationTest < ApplicationIntegrationTest - setup do - sign_in users(:registrant) - end - - def test_downloads_list_as_csv - get registrant_domains_path(format: :csv) - - assert_response :ok - assert_equal "#{Mime[:csv]}; charset=utf-8", response.headers['Content-Type'] - assert_equal "attachment; filename=\"domains.csv\"; filename*=UTF-8''domains.csv", response.headers['Content-Disposition'] - assert_not_empty response.body - end - - def test_downloads_list_as_pdf - get registrant_domains_path(format: :pdf) - - assert_response :ok - assert_equal Mime[:pdf], response.headers['Content-Type'] - assert_equal "attachment; filename=\"domains.pdf\"; filename*=UTF-8''domains.pdf", response.headers['Content-Disposition'] - assert_not_empty response.body - end -end diff --git a/test/integration/repp/v1/accounts/balance_test.rb b/test/integration/repp/v1/accounts/balance_test.rb index 785e0aee8..4b711bd05 100644 --- a/test/integration/repp/v1/accounts/balance_test.rb +++ b/test/integration/repp/v1/accounts/balance_test.rb @@ -2,6 +2,7 @@ require 'test_helper' class ReppV1BalanceTest < ActionDispatch::IntegrationTest def setup + travel_to Time.zone.parse('2010-07-05') @registrar = users(:api_bestnames) token = Base64.encode64("#{@registrar.username}:#{@registrar.plain_text_password}") token = "Basic #{token}" @@ -19,4 +20,32 @@ class ReppV1BalanceTest < ActionDispatch::IntegrationTest assert_equal @registrar.registrar.cash_account.balance.to_s, json[:data][:balance] assert_equal @registrar.registrar.cash_account.currency, json[:data][:currency] end + + def test_can_query_balance_with_details + # Create new billable action to get activity + post "/repp/v1/domains/renew/bulk", headers: @auth_headers, params: { domains: ['shop.test'], renew_period: '1y' } + + started_from = "2010-07-05" + end_to = DateTime.current.to_date.to_s(:db) + + get "/repp/v1/accounts/balance?detailed=true", headers: @auth_headers + json = JSON.parse(response.body, symbolize_names: true) + + assert_response :ok + assert_equal 1000, json[:code] + assert_equal 'Command completed successfully', json[:message] + assert_equal @registrar.registrar.cash_account.balance.to_s, json[:data][:balance] + assert_equal @registrar.registrar.cash_account.currency, json[:data][:currency] + entry = json[:data][:transactions].last + assert_equal @registrar.registrar.cash_account.account_activities.last.created_at, entry[:created_at] + assert_equal @registrar.registrar.cash_account.account_activities.last.description, entry[:description] + assert_equal 'debit', entry[:type] + assert_equal @registrar.registrar.cash_account.account_activities.last.sum.to_s, entry[:sum] + assert_equal @registrar.registrar.cash_account.account_activities.last.new_balance.to_s, entry[:balance] + + json[:data][:transactions].map do |trans| + assert trans[:created_at].to_date.to_s(:db) >= started_from + assert trans[:created_at].to_date.to_s(:db) >= end_to + end + end end diff --git a/test/integration/repp/v1/domains/bulk_renew_test.rb b/test/integration/repp/v1/domains/bulk_renew_test.rb index 4cec91914..46e2fbf7d 100644 --- a/test/integration/repp/v1/domains/bulk_renew_test.rb +++ b/test/integration/repp/v1/domains/bulk_renew_test.rb @@ -37,6 +37,29 @@ class ReppV1DomainsBulkRenewTest < ActionDispatch::IntegrationTest end end + def test_keeps_update_prohibited_status + domain = domains(:shop) + domain.update(statuses: [DomainStatus::CLIENT_UPDATE_PROHIBITED, DomainStatus::SERVER_UPDATE_PROHIBITED]) + payload = { + "domains": [ + 'shop.test' + ], + "renew_period": "1y" + } + + assert_changes -> { Domain.find_by(name: 'shop.test').valid_to } do + post "/repp/v1/domains/renew/bulk", headers: @auth_headers, params: payload + json = JSON.parse(response.body, symbolize_names: true) + + assert_response :ok + assert_equal 1000, json[:code] + assert_equal 'Command completed successfully', json[:message] + assert json[:data][:updated_domains].include? 'shop.test' + end + domain.reload + assert_equal domain.statuses, [DomainStatus::CLIENT_UPDATE_PROHIBITED, DomainStatus::SERVER_UPDATE_PROHIBITED] + end + def test_throws_error_when_domain_not_renewable payload = { "domains": [ diff --git a/test/integration/repp/v1/registrar/nameservers_test.rb b/test/integration/repp/v1/registrar/nameservers_test.rb index f01769dfb..e2c6f890b 100644 --- a/test/integration/repp/v1/registrar/nameservers_test.rb +++ b/test/integration/repp/v1/registrar/nameservers_test.rb @@ -34,6 +34,33 @@ class ReppV1RegistrarNameserversTest < ActionDispatch::IntegrationTest assert json[:data][:affected_domains].include? 'shop.test' end + def test_fails_to_update_if_prohibited + domain = domains(:shop) + domain.update(statuses: [DomainStatus::CLIENT_UPDATE_PROHIBITED]) + nameserver = nameservers(:shop_ns1) + payload = { + "data": { + "id": nameserver.hostname, + "type": "nameserver", + "attributes": { + "hostname": "#{nameserver.hostname}.test", + "ipv4": ["1.1.1.1"] + } + } + } + + put '/repp/v1/registrar/nameservers', headers: @auth_headers, params: payload + json = JSON.parse(response.body, symbolize_names: true) + + assert_response :ok + assert_equal 1000, json[:code] + assert_equal 'Command completed successfully', json[:message] + assert_equal({ hostname: "#{nameserver.hostname}.test", ipv4: ["1.1.1.1"] }, json[:data][:attributes]) + assert_equal({ hostname: "#{nameserver.hostname}.test", ipv4: ["1.1.1.1"] }, json[:data][:attributes]) + assert json[:data][:affected_domains].include? 'airport.test' + assert json[:data][:skipped_domains].include? 'shop.test' + end + def test_nameserver_with_hostname_must_exist payload = { "data": { diff --git a/test/integration/repp/v1/retained_domains_test.rb b/test/integration/repp/v1/retained_domains_test.rb index 1c9f49f58..824c826ef 100644 --- a/test/integration/repp/v1/retained_domains_test.rb +++ b/test/integration/repp/v1/retained_domains_test.rb @@ -21,7 +21,7 @@ class ReppV1RetainedDomainsTest < ActionDispatch::IntegrationTest status: 'reserved', punycode_name: 'reserved.test' }] - assert_equal response_json[:domains], expected_objects + assert_empty response_json[:domains] - expected_objects end def test_get_index_with_type_parameter @@ -77,7 +77,7 @@ class ReppV1RetainedDomainsTest < ActionDispatch::IntegrationTest status: 'disputed', punycode_name: 'reserved.test' }] - assert_equal response_json[:domains], expected_objects + assert_empty response_json[:domains] - expected_objects end def test_etags_cache diff --git a/test/jobs/domain_update_confirm_job_test.rb b/test/jobs/domain_update_confirm_job_test.rb index ded0d3d8a..d2d3a3252 100644 --- a/test/jobs/domain_update_confirm_job_test.rb +++ b/test/jobs/domain_update_confirm_job_test.rb @@ -1,5 +1,4 @@ require "test_helper" - class DomainUpdateConfirmJobTest < ActiveSupport::TestCase def setup super @@ -19,6 +18,22 @@ class DomainUpdateConfirmJobTest < ActiveSupport::TestCase super end + def test_registrant_locked_domain + refute @domain.locked_by_registrant? + @domain.apply_registry_lock + assert @domain.locked_by_registrant? + assert_equal(@domain.registrar.notifications.last.text, "Domain #{@domain.name} has been locked by registrant") + end + + def test_registrant_unlocked_domain + refute @domain.locked_by_registrant? + @domain.apply_registry_lock + assert @domain.locked_by_registrant? + @domain.remove_registry_lock + refute @domain.locked_by_registrant? + assert_equal(@domain.registrar.notifications.last.text, "Domain #{@domain.name} has been unlocked by registrant") + end + def test_rejected_registrant_verification_notifies_registrar DomainUpdateConfirmJob.perform_now(@domain.id, RegistrantVerification::REJECTED) diff --git a/test/lib/serializers/registrant_api/domain_test.rb b/test/lib/serializers/registrant_api/domain_test.rb index f2623741f..2e68e4293 100644 --- a/test/lib/serializers/registrant_api/domain_test.rb +++ b/test/lib/serializers/registrant_api/domain_test.rb @@ -30,8 +30,15 @@ class SerializersRegistrantApiDomainTest < ActiveSupport::TestCase assert_equal({name: 'Best Names', website: 'https://bestnames.test' }, @json[:registrar]) end - def test_returns_registrant_name_and_uuid - assert_equal({name: 'John', id: 'eb2f2766-b44c-4e14-9f16-32ab1a7cb957'}, + def test_returns_registrant_name_uuid_and_org + assert_equal({:name=>"John", + :id=>"eb2f2766-b44c-4e14-9f16-32ab1a7cb957", + :ident=>"1234", + :ident_type=>"priv", + :ident_country_code=>"US", + :phone=>"+555.555", + :email=>"john@inbox.test", + :org=>false}, @json[:registrant]) end diff --git a/test/mailers/registrant_change_mailer_test.rb b/test/mailers/registrant_change_mailer_test.rb index 5d14972e3..5ddfc76db 100644 --- a/test/mailers/registrant_change_mailer_test.rb +++ b/test/mailers/registrant_change_mailer_test.rb @@ -72,11 +72,14 @@ class RegistrantChangeMailerTest < ActionMailer::TestCase email = RegistrantChangeMailer.expired(domain: @domain, registrar: @domain.registrar, - registrant: @domain.registrant).deliver_now + registrant: @domain.registrant, + send_to: [@domain.new_registrant_email, + @domain.registrant.email], + ).deliver_now assert_emails 1 - assert_equal ['william@inbox.test'], email.to + assert_equal ['william@inbox.test', @domain.registrant.email], email.to assert_equal 'Domeeni shop.test registreerija vahetuse taotlus on tühistatud' \ ' / shop.test registrant change cancelled', email.subject end -end \ No newline at end of file +end diff --git a/test/models/concerns/versions_test.rb b/test/models/concerns/versions_test.rb index 2a54b4476..bc823d51c 100644 --- a/test/models/concerns/versions_test.rb +++ b/test/models/concerns/versions_test.rb @@ -7,7 +7,7 @@ class VersionsTest < ActiveSupport::TestCase @nameserver.update(hostname: 'ns99.bestnames.test') @ignored_column_title = Nameserver.ignored_columns.first - version = NameserverVersion.last + version = Version::NameserverVersion.last hash = version.object hash[@ignored_column_title] = 123456 version.update(object: hash) diff --git a/test/models/contact/archivable_test.rb b/test/models/contact/archivable_test.rb index 340ca54e0..cd07d3894 100644 --- a/test/models/contact/archivable_test.rb +++ b/test/models/contact/archivable_test.rb @@ -6,8 +6,8 @@ class ArchivableContactTest < ActiveSupport::TestCase end def test_contact_is_archivable_when_it_was_linked_and_inactivity_period_has_passed - DomainVersion.stub(:was_contact_linked?, true) do - DomainVersion.stub(:contact_unlinked_more_than?, true) do + Version::DomainVersion.stub(:was_contact_linked?, true) do + Version::DomainVersion.stub(:contact_unlinked_more_than?, true) do assert @contact.archivable? end end @@ -18,7 +18,7 @@ class ArchivableContactTest < ActiveSupport::TestCase @contact.created_at = Time.zone.parse('2010-07-05 00:00:00') travel_to Time.zone.parse('2010-07-05 00:00:01') - DomainVersion.stub(:was_contact_linked?, false) do + Version::DomainVersion.stub(:was_contact_linked?, false) do assert @contact.archivable? end end @@ -28,14 +28,14 @@ class ArchivableContactTest < ActiveSupport::TestCase @contact.created_at = Time.zone.parse('2010-07-05') travel_to Time.zone.parse('2010-07-05') - DomainVersion.stub(:contact_unlinked_more_than?, false) do + Version::DomainVersion.stub(:contact_unlinked_more_than?, false) do assert_not @contact.archivable? end end def test_contact_is_not_archivable_when_it_was_ever_linked_but_linked_within_inactivity_period - DomainVersion.stub(:was_contact_linked?, true) do - DomainVersion.stub(:contact_unlinked_more_than?, false) do + Version::DomainVersion.stub(:was_contact_linked?, true) do + Version::DomainVersion.stub(:contact_unlinked_more_than?, false) do assert_not @contact.archivable? end end @@ -73,7 +73,7 @@ class ArchivableContactTest < ActiveSupport::TestCase def archivable_contact contact = contacts(:john) Setting.orphans_contacts_in_months = 0 - DomainVersion.delete_all + Version::DomainVersion.delete_all other_contact = contacts(:william) assert_not_equal other_contact, contact diff --git a/test/models/domain/force_delete_test.rb b/test/models/domain/force_delete_test.rb index 2bb1b5b8f..19338f495 100644 --- a/test/models/domain/force_delete_test.rb +++ b/test/models/domain/force_delete_test.rb @@ -234,6 +234,19 @@ class ForceDeleteTest < ActionMailer::TestCase assert_includes(@domain.statuses, asserted_status) end + def test_client_hold_prohibits_manual_inzone + @domain.update(valid_to: Time.zone.parse('2012-08-05')) + @domain.update(template_name: 'legal_person') + travel_to Time.zone.parse('2010-07-05') + @domain.schedule_force_delete(type: :soft) + travel_to Time.zone.parse('2010-08-21') + Domains::ClientHold::SetClientHold.run! + @domain.reload + + @domain.statuses << DomainStatus::SERVER_MANUAL_INZONE + assert_not @domain.valid? + end + def test_force_delete_soft_year_ahead_not_sets_client_hold_before_threshold asserted_status = DomainStatus::CLIENT_HOLD diff --git a/test/models/domain/releasable/auctionable_test.rb b/test/models/domain/releasable/auctionable_test.rb index de3ac0ff6..d24f46913 100644 --- a/test/models/domain/releasable/auctionable_test.rb +++ b/test/models/domain/releasable/auctionable_test.rb @@ -25,6 +25,7 @@ class DomainReleasableAuctionableTest < ActiveSupport::TestCase def test_skips_auction_when_domains_is_blocked assert_equal 'shop.test', @domain.name blocked_domains(:one).update!(name: 'shop.test') + @domain.save!(validate: false) @domain.release @@ -34,6 +35,7 @@ class DomainReleasableAuctionableTest < ActiveSupport::TestCase def test_skips_auction_when_domains_is_reserved assert_equal 'shop.test', @domain.name reserved_domains(:one).update!(name: 'shop.test') + @domain.save!(validate: false) @domain.release @@ -58,6 +60,24 @@ class DomainReleasableAuctionableTest < ActiveSupport::TestCase end end + def test_updates_whois_server + @domain.update!(delete_date: '2010-07-04') + travel_to Time.zone.parse('2010-07-05') + old_whois = @domain.whois_record + + Domain.release_domains + + assert_raises ActiveRecord::RecordNotFound do + old_whois.reload + end + + whois_record = Whois::Record.find_by(name: @domain.name) + json = { "name"=>@domain.name, + "status"=>["AtAuction"], + "disclaimer"=> Setting.registry_whois_disclaimer } + assert_equal whois_record.json, json + end + def test_notifies_registrar @domain.update!(delete_date: '2010-07-04') travel_to Time.zone.parse('2010-07-05') diff --git a/test/models/domain_test.rb b/test/models/domain_test.rb index ae12f4a1e..15ab8b0c2 100644 --- a/test/models/domain_test.rb +++ b/test/models/domain_test.rb @@ -69,6 +69,12 @@ class DomainTest < ActiveSupport::TestCase domain.name = 'xn--mnchen-3ya.test' assert domain.valid? + + domain.name = '####' + assert domain.invalid? + + domain.name = 'https://example.test' + assert domain.invalid? end def test_invalid_when_name_is_already_taken diff --git a/test/models/registrant_verification_test.rb b/test/models/registrant_verification_test.rb index ef4038784..a8707fd85 100644 --- a/test/models/registrant_verification_test.rb +++ b/test/models/registrant_verification_test.rb @@ -15,7 +15,7 @@ class RegistrantVerificationTest < ActiveSupport::TestCase registrant_verification = registrant_verifications(:one) random_action = "random#{rand(100)}" - assert_difference -> { RegistrantVerificationVersion.count } do + assert_difference -> { Version::RegistrantVerificationVersion.count } do registrant_verification.update_attributes!(action: random_action) end end @@ -23,11 +23,11 @@ class RegistrantVerificationTest < ActiveSupport::TestCase def test_reject_changes @registrant_verification = RegistrantVerification.new(domain_id: @domain.id, verification_token: @token) - start_versions_count = RegistrantVerificationVersion.count + start_versions_count = Version::RegistrantVerificationVersion.count assert_nothing_raised do @registrant_verification.domain_registrant_change_reject!("email link, #{@initiator}") end - assert_equal RegistrantVerificationVersion.count, start_versions_count + 1 + assert_equal Version::RegistrantVerificationVersion.count, start_versions_count + 1 end end diff --git a/test/models/version/domain_version_test.rb b/test/models/version/domain_version_test.rb index 719fcf3ba..be8b020c4 100644 --- a/test/models/version/domain_version_test.rb +++ b/test/models/version/domain_version_test.rb @@ -11,7 +11,7 @@ class DomainVersionTest < ActiveSupport::TestCase tech_contacts: [], registrant: [@contact.id] }) - assert DomainVersion.was_contact_linked?(@contact.id) + assert Version::DomainVersion.was_contact_linked?(@contact.id) end def test_was_contact_linked_returns_true_when_contact_was_used_as_admin_contact @@ -19,7 +19,7 @@ class DomainVersionTest < ActiveSupport::TestCase tech_contacts: [], registrant: [] }) - assert DomainVersion.was_contact_linked?(@contact.id) + assert Version::DomainVersion.was_contact_linked?(@contact.id) end def test_was_contact_linked_returns_true_when_contact_was_used_as_tech_contact @@ -27,7 +27,7 @@ class DomainVersionTest < ActiveSupport::TestCase tech_contacts: [@contact.id], registrant: [] }) - assert DomainVersion.was_contact_linked?(@contact.id) + assert Version::DomainVersion.was_contact_linked?(@contact.id) end def test_was_contact_linked_returns_false_when_contact_was_not_used @@ -35,7 +35,7 @@ class DomainVersionTest < ActiveSupport::TestCase tech_contacts: [], registrant: [] }) - assert_not DomainVersion.was_contact_linked?(@contact.id) + assert_not Version::DomainVersion.was_contact_linked?(@contact.id) end def test_contact_unlinked_more_than_returns_true_when_contact_was_linked_as_registrant_more_than_given_period @@ -45,7 +45,7 @@ class DomainVersionTest < ActiveSupport::TestCase registrant: [@contact.id] }) travel_to Time.zone.parse('2010-07-05 00:00:01') - assert DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) + assert Version::DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) end def test_contact_unlinked_more_than_given_period_as_admin_contact @@ -55,7 +55,7 @@ class DomainVersionTest < ActiveSupport::TestCase registrant: [] }) travel_to Time.zone.parse('2010-07-05 00:00:01') - assert DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) + assert Version::DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) end def test_contact_unlinked_more_than_given_period_as_tech_contact @@ -65,7 +65,7 @@ class DomainVersionTest < ActiveSupport::TestCase registrant: [] }) travel_to Time.zone.parse('2010-07-05 00:00:01') - assert DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) + assert Version::DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) end def test_contact_linked_within_given_period_as_registrant @@ -75,7 +75,7 @@ class DomainVersionTest < ActiveSupport::TestCase registrant: [@contact.id] }) travel_to Time.zone.parse('2010-07-05') - assert_not DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) + assert_not Version::DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) end def test_contact_linked_within_given_period_as_admin_contact @@ -85,7 +85,7 @@ class DomainVersionTest < ActiveSupport::TestCase registrant: [] }) travel_to Time.zone.parse('2010-07-05') - assert_not DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) + assert_not Version::DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) end def test_contact_linked_within_given_period_as_tech_contact @@ -95,11 +95,11 @@ class DomainVersionTest < ActiveSupport::TestCase registrant: [] }) travel_to Time.zone.parse('2010-07-05') - assert_not DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) + assert_not Version::DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) end def test_contact_was_never_linked - DomainVersion.delete_all - assert_not DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) + Version::DomainVersion.delete_all + assert_not Version::DomainVersion.contact_unlinked_more_than?(contact_id: @contact.id, period: 1.day) end end diff --git a/test/models/white_ip_test.rb b/test/models/white_ip_test.rb index 607887730..ba5abe42f 100644 --- a/test/models/white_ip_test.rb +++ b/test/models/white_ip_test.rb @@ -38,6 +38,20 @@ class WhiteIpTest < ActiveSupport::TestCase assert white_ip.valid? end + def test_validates_include_empty_ipv4 + white_ip = WhiteIp.new + + white_ip.ipv4 = nil + white_ip.ipv6 = '001:0db8:85a3:0000:0000:8a2e:0370:7334' + white_ip.registrar = registrars(:bestnames) + + assert_nothing_raised { white_ip.save } + assert white_ip.valid? + + assert WhiteIp.include_ip?(white_ip.ipv6) + assert_not WhiteIp.include_ip?('192.168.1.1') + end + private def valid_white_ip diff --git a/test/system/admin_area/bank_statement_test.rb b/test/system/admin_area/bank_statement_test.rb index 6de21b1c3..8630049dc 100644 --- a/test/system/admin_area/bank_statement_test.rb +++ b/test/system/admin_area/bank_statement_test.rb @@ -4,6 +4,35 @@ class AdminAreaBankStatementTest < ApplicationSystemTestCase setup do sign_in users(:admin) travel_to Time.zone.parse('2010-07-05 00:30:00') + + @invoice = invoices(:one) + end + + def test_update_bank_statement + visit admin_bank_statement_path(id: @invoice.id) + + click_link_or_button 'Add' + + fill_in 'Description', with: 'Invoice with id 123' + fill_in 'Reference number', with: '1232' + fill_in 'Sum', with: '500' + fill_in 'Paid at', with: Time.zone.today.to_s + + click_link_or_button 'Save' + assert_text 'Bank transaction' + + click_link_or_button 'Edit' + fill_in 'Description', with: 'Invoice with id 123' + click_link_or_button 'Save' + + assert_text 'Record updated' + end + + def test_bind_bank + visit admin_bank_statement_path(id: @invoice.id) + click_link_or_button 'Bind invoices' + + assert_text 'No invoices were binded' end def test_can_create_statement_manually diff --git a/test/system/admin_area/contacts_test.rb b/test/system/admin_area/contacts_test.rb index d98882dff..19b15c8a5 100644 --- a/test/system/admin_area/contacts_test.rb +++ b/test/system/admin_area/contacts_test.rb @@ -8,6 +8,17 @@ class AdminContactsTest < ApplicationSystemTestCase sign_in users(:admin) end + def test_update_contact + visit admin_contact_path(id: @contact.id) + assert_text "#{@contact.name}" + + click_on 'Edit statuses' + assert_text "Edit: #{@contact.name}" + + click_on 'Save' + assert_text 'Contact updated' + end + def test_display_list visit admin_contacts_path diff --git a/test/system/admin_area/domains/csv_test.rb b/test/system/admin_area/domains/csv_test.rb new file mode 100644 index 000000000..7d4b44124 --- /dev/null +++ b/test/system/admin_area/domains/csv_test.rb @@ -0,0 +1,18 @@ +require 'application_system_test_case' + +class AdminAreaCsvTest < ApplicationSystemTestCase + setup do + sign_in users(:admin) + end + + def test_downloads_domain_list_as_csv + search_params = {"valid_to_lteq"=>nil} + expected_csv = Domain.includes(:registrar, :registrant).search(search_params).result.to_csv + + travel_to Time.zone.parse('2010-07-05 10:30') + visit admin_domains_url + click_link('CSV') + assert_equal "attachment; filename=\"domains.csv\"; filename*=UTF-8''domains.csv", response_headers['Content-Disposition'] + assert_equal expected_csv, page.body + end +end diff --git a/test/system/admin_area/domains/legal_doc_test.rb b/test/system/admin_area/domains/legal_doc_test.rb index 00cc7cc3a..48eedcf4f 100644 --- a/test/system/admin_area/domains/legal_doc_test.rb +++ b/test/system/admin_area/domains/legal_doc_test.rb @@ -15,7 +15,7 @@ class AdminAreaDomainsLegalDocTest < ApplicationSystemTestCase def test_absent_doc_downloading_without_errors visit admin_domain_url(@domain) assert_nothing_raised do - click_on "#{@document.created_at}" + click_on "#{@document.created_at}", match: :first end end end diff --git a/test/system/admin_area/invoices_test.rb b/test/system/admin_area/invoices_test.rb index 814f95d4a..40a50e1c7 100644 --- a/test/system/admin_area/invoices_test.rb +++ b/test/system/admin_area/invoices_test.rb @@ -40,4 +40,4 @@ class AdminAreaInvoicesTest < ApplicationSystemTestCase assert_current_path admin_invoice_path(@invoice) assert_text 'Invoice has been sent' end -end \ No newline at end of file +end diff --git a/test/system/admin_area/prices_test.rb b/test/system/admin_area/prices_test.rb index dbb91966a..f5a299c38 100644 --- a/test/system/admin_area/prices_test.rb +++ b/test/system/admin_area/prices_test.rb @@ -20,6 +20,7 @@ class AdminAreaPricesTest < ApplicationSystemTestCase fill_in 'Valid from', with: effective_date click_on 'Create price' + assert_text 'Price has been created' assert_text I18n.localize(effective_date) end diff --git a/test/system/admin_area/protected_area_test.rb b/test/system/admin_area/protected_area_test.rb index f3375776a..fa413291b 100644 --- a/test/system/admin_area/protected_area_test.rb +++ b/test/system/admin_area/protected_area_test.rb @@ -19,4 +19,4 @@ class AdminAreaProtectedAreaTest < ApplicationSystemTestCase assert_text 'You are already signed in' assert_current_path admin_domains_path end -end \ No newline at end of file +end diff --git a/test/system/registrant_area/contacts/details_test.rb b/test/system/registrant_area/contacts/details_test.rb deleted file mode 100644 index bf96046a6..000000000 --- a/test/system/registrant_area/contacts/details_test.rb +++ /dev/null @@ -1,33 +0,0 @@ -require 'application_system_test_case' - -class RegistrantAreaContactDetailsTest < ApplicationSystemTestCase - setup do - sign_in users(:registrant) - @domain = domains(:shop) - @contact = contacts(:john) - end - - def test_general_data - visit registrant_domain_contact_url(@domain, @contact) - assert_text 'Code john-001' - assert_text 'Name John' - - assert_text 'Auth info' - assert_css('[value="cacb5b"]') - - assert_text 'Ident 1234' - assert_text 'Email john@inbox.test' - assert_text 'Phone +555.555' - - assert_text "Created at #{l Time.zone.parse('2010-07-05')}" - assert_text "Updated at #{l Time.zone.parse('2010-07-06')}" - end - - def test_registrant_user_cannot_access_contact_when_given_domain_belongs_to_another_user - suppress(ActiveRecord::RecordNotFound) do - visit registrant_domain_contact_url(domains(:metro), @contact) - assert_response :not_found - assert_no_text 'Name John' - end - end -end diff --git a/test/system/registrant_area/contacts/update_test.rb b/test/system/registrant_area/contacts/update_test.rb deleted file mode 100644 index 07115579b..000000000 --- a/test/system/registrant_area/contacts/update_test.rb +++ /dev/null @@ -1,172 +0,0 @@ -require 'application_system_test_case' - -class RegistrantAreaContactUpdateTest < ApplicationIntegrationTest - setup do - @domain = domains(:shop) - @contact = contacts(:john) - sign_in users(:registrant) - - @original_address_processing = Setting.address_processing - @original_fax_enabled_setting = ENV['fax_enabled'] - @original_registrant_api_base_url_setting = ENV['registrant_api_base_url'] - - ENV['registrant_api_base_url'] = 'https://api.test' - end - - teardown do - Setting.address_processing = @original_address_processing - ENV['fax_enabled'] = @original_fax_enabled_setting - ENV['registrant_api_base_url'] = @original_registrant_api_base_url_setting - end - - def test_form_is_pre_populated_with_contact_data - visit edit_registrant_domain_contact_url(@domain, @contact) - - assert_field 'Name', with: 'John' - assert_field 'Email', with: 'john@inbox.test' - assert_field 'Phone', with: '+555.555' - end - - def test_update_contact - stub_auth_request - - request_body = { name: 'new name', email: 'new@inbox.test', phone: '+666.6' }.to_json - headers = { 'Content-Type' => Mime[:json], - 'Authorization' => 'Bearer test-access-token' } - url = "https://api.test/api/v1/registrant/contacts/#{@contact.uuid}" - update_request_stub = stub_request(:patch, url).with(body: request_body, headers: headers) - .to_return(body: '{}', status: 200) - - visit registrant_domain_contact_url(@domain, @contact) - click_link_or_button 'Edit' - - fill_in 'Name', with: 'new name' - fill_in 'Email', with: 'new@inbox.test' - fill_in 'Phone', with: '+666.6' - - click_link_or_button 'Update contact' - - assert_requested update_request_stub - assert_current_path registrant_domain_contact_path(@domain, @contact) - assert_text 'Contact has been successfully updated' - end - - def test_form_is_pre_populated_with_fax_when_enabled - ENV['fax_enabled'] = 'true' - @contact.update!(fax: '+111.1') - - visit edit_registrant_domain_contact_url(@domain, @contact) - assert_field 'Fax', with: '+111.1' - end - - def test_update_fax_when_enabled - ENV['fax_enabled'] = 'true' - stub_auth_request - - request_body = { email: 'john@inbox.test', name: 'John', phone: '+555.555', fax: '+222.2' } - headers = { 'Authorization' => 'Bearer test-access-token' } - url = "https://api.test/api/v1/registrant/contacts/#{@contact.uuid}" - update_request_stub = stub_request(:patch, url).with(body: request_body, headers: headers) - .to_return(body: '{}', status: 200) - - visit edit_registrant_domain_contact_url(@domain, @contact) - - fill_in 'Fax', with: '+222.2' - click_link_or_button 'Update contact' - - assert_requested update_request_stub - assert_current_path registrant_domain_contact_path(@domain, @contact) - assert_text 'Contact has been successfully updated' - end - - def test_hide_fax_field_when_disabled - visit edit_registrant_domain_contact_url(@domain, @contact) - assert_no_field 'Fax' - end - - def test_form_is_pre_populated_with_address_when_enabled - Setting.address_processing = true - @contact.update!(street: 'Main Street', - zip: '12345', - city: 'New York', - state: 'New York State', - country_code: 'US') - - visit edit_registrant_domain_contact_url(@domain, @contact) - - assert_field 'Street', with: 'Main Street' - assert_field 'Zip', with: '12345' - assert_field 'City', with: 'New York' - assert_field 'State', with: 'New York State' - assert_select 'Country', selected: 'United States' - end - - def test_update_address_when_enabled - Setting.address_processing = true - stub_auth_request - - request_body = { name: 'John', - email: 'john@inbox.test', - phone: '+555.555', - address: { - city: 'new city', - street: 'new street', - zip: '93742', - country_code: 'AT', - state: 'new state', - } }.to_json - headers = { 'Content-type' => Mime[:json], - 'Authorization' => 'Bearer test-access-token' } - url = "https://api.test/api/v1/registrant/contacts/#{@contact.uuid}" - update_request_stub = stub_request(:patch, url).with(body: request_body, headers: headers) - .to_return(body: '{}', status: 200) - - visit edit_registrant_domain_contact_url(@domain, @contact) - - fill_in 'Street', with: 'new street' - fill_in 'City', with: 'new city' - fill_in 'State', with: 'new state' - fill_in 'Zip', with: '93742' - select 'Austria', from: 'Country' - click_link_or_button 'Update contact' - - assert_requested update_request_stub - assert_current_path registrant_domain_contact_path(@domain, @contact) - assert_text 'Contact has been successfully updated' - end - - def test_hide_address_field_when_disabled - visit edit_registrant_domain_contact_url(@domain, @contact) - assert_no_field 'Address' - assert_no_field 'Street' - end - - def test_fail_gracefully - stub_auth_request - - response_body = { errors: { name: ['Name is invalid'] } }.to_json - headers = { 'Authorization' => 'Bearer test-access-token' } - stub_request(:patch, "https://api.test/api/v1/registrant/contacts/#{@contact.uuid}") - .with(headers: headers) - .to_return(body: response_body, status: 400) - - visit edit_registrant_domain_contact_url(@domain, @contact) - fill_in 'Name', with: 'invalid name' - click_link_or_button 'Update contact' - - assert_current_path registrant_domain_contact_path(@domain, @contact) - assert_text 'Name is invalid' - assert_field 'Name', with: 'invalid name' - assert_no_text 'Contact has been successfully updated' - end - - private - - def stub_auth_request - body = { ident: '1234', first_name: 'Registrant', last_name: 'User' } - stub_request(:post, 'https://api.test/api/v1/registrant/auth/eid').with(body: body) - .to_return(body: { access_token: 'test-access-token' }.to_json, - headers: { 'Content-type' => Mime[:json] }, - status: 200) - end -end diff --git a/test/system/registrant_area/domains/details_test.rb b/test/system/registrant_area/domains/details_test.rb deleted file mode 100644 index 2f61d46be..000000000 --- a/test/system/registrant_area/domains/details_test.rb +++ /dev/null @@ -1,76 +0,0 @@ -require 'application_system_test_case' - -class RegistrantAreaDomainDetailsTest < ApplicationSystemTestCase - setup do - sign_in users(:registrant) - @domain = domains(:shop) - end - - def test_general_data - @domain.update_columns(force_delete_date: '2010-07-08', statuses: [DomainStatus::FORCE_DELETE]) - - visit registrant_domain_url(@domain) - - assert_text 'Name shop.test' - assert_text "Registered at #{l @domain.registered_at}" - assert_link 'Best Names', href: registrant_registrar_path(@domain.registrar) - - assert_text 'Transfer code' - assert_css('[value="65078d5"]') - - assert_text "Valid to #{l Time.zone.parse('2010-07-05')}" - assert_text "Outzone at #{l Time.zone.parse('2010-07-06')}" - assert_text "Delete date #{l Date.parse('2010-07-07')}" - assert_text "Force delete date #{l Date.parse('2010-07-08')}" - end - - def test_registrant - visit registrant_domain_url(@domain) - assert_link 'John', href: registrant_domain_contact_path(@domain, @domain.registrant) - assert_text 'Code john-001' - assert_text 'Ident 1234' - assert_text 'Email john@inbox.test' - assert_text 'Phone +555.555' - end - - def test_admin_contacts - visit registrant_domain_url(@domain) - - within('.admin-domain-contacts') do - assert_link 'Jane', href: registrant_domain_contact_path(@domain, contacts(:jane)) - assert_text 'jane-001' - assert_text 'jane@mail.test' - assert_css '.admin-domain-contact', count: 1 - end - end - - def test_tech_contacts - visit registrant_domain_url(@domain) - - within('.tech-domain-contacts') do - assert_link 'William', href: registrant_domain_contact_path(@domain, contacts(:william)) - assert_text 'william-001' - assert_text 'william@inbox.test' - assert_css '.tech-domain-contact', count: 2 - end - end - - def test_registrant_user_cannot_access_domains_of_other_users - suppress(ActiveRecord::RecordNotFound) do - visit registrant_domain_url(domains(:metro)) - assert_response :not_found - assert_no_text 'metro.test' - end - end - - def test_confirmation_url - @domain.update!(registrant_verification_token: 'a01', - pending_json: { new_registrant_email: 'any' }, - statuses: [DomainStatus::PENDING_UPDATE]) - - visit registrant_domain_url(@domain) - click_on 'pendingUpdate' - - assert_field nil, with: registrant_domain_update_confirm_url(@domain, token: 'a01') - end -end diff --git a/test/system/registrant_area/domains/domain_delete_confirms_test.rb b/test/system/registrant_area/domains/domain_delete_confirms_test.rb deleted file mode 100644 index 765cd0149..000000000 --- a/test/system/registrant_area/domains/domain_delete_confirms_test.rb +++ /dev/null @@ -1,46 +0,0 @@ -require 'application_system_test_case' - -class DomainDeleteConfirmsTest < ApplicationSystemTestCase - include ActionMailer::TestHelper - setup do - @user = users(:registrant) - sign_in @user - - @domain = domains(:shop) - @domain.registrant_verification_asked!('\n', @user.id) - @domain.pending_delete! - end - - def test_enqueues_approve_job_after_verification - visit registrant_domain_delete_confirm_url(@domain.id, token: @domain.registrant_verification_token) - - perform_enqueued_jobs do - click_on 'Confirm domain delete' - end - assert_text 'Domain registrant change has successfully received.' - - @domain.reload - assert_includes @domain.statuses, 'serverHold' - end - - def test_enqueues_reject_job_after_verification - visit registrant_domain_delete_confirm_url(@domain.id, token: @domain.registrant_verification_token) - - perform_enqueued_jobs do - click_on 'Reject domain delete' - end - assert_text 'Domain registrant change has been rejected successfully.' - - @domain.reload - assert_equal ['ok'], @domain.statuses - end - - def test_saves_whodunnit_info_after_verifivation - visit registrant_domain_delete_confirm_url(@domain.id, token: @domain.registrant_verification_token) - token = @domain.registrant_verification_token - click_on 'Confirm domain delete' - assert_text 'Domain registrant change has successfully received.' - - refute RegistrantVerification.find_by(verification_token:token).updator_str.empty? - end -end diff --git a/test/system/registrant_area/domains/list_test.rb b/test/system/registrant_area/domains/list_test.rb deleted file mode 100644 index 3cbf477da..000000000 --- a/test/system/registrant_area/domains/list_test.rb +++ /dev/null @@ -1,71 +0,0 @@ -require 'application_system_test_case' - -CompanyRegisterClientStub = Struct.new(:any_method) do - def representation_rights(citizen_personal_code:, citizen_country_code:) - raise CompanyRegister::NotAvailableError - end -end - -class RegistrantAreaDomainListTest < ApplicationSystemTestCase - setup do - @user = users(:registrant) - sign_in @user - - @domain = domains(:shop) - end - - def test_show_domain_list - visit registrant_domains_url - assert_link 'shop.test', href: registrant_domain_path(@domain) - assert_link 'John', href: registrant_domain_contact_path(@domain, @domain.registrant) - assert_link 'Best Names', href: registrant_registrar_path(@domain.registrar) - assert_text l(Time.zone.parse('2010-07-05')) - assert_css '.domains .domain', count: 4 - end - - def test_do_not_show_domains_of_other_registrant_users - visit registrant_domains_url - assert_no_text 'metro.test' - end - - def test_only_shows_direct_relation_and_or_company_domains - # case https://github.com/internetee/registry/issues/1690 - tech_contact = contacts(:registrar_ltd) - - # All domains share the same tech contact object - Domain.all.each do |domain| - DomainContact.create(domain: domain, contact: tech_contact, type: TechDomainContact) - end - - visit registrant_domains_url - assert_no_text 'Company register is unavailable.' - assert_no_text 'metro.test' - end - - def test_notification_when_company_register_is_unavailable - CompanyRegister::Client.stub(:new, CompanyRegisterClientStub.new) do - visit registrant_domains_url - end - - assert_text 'Company register is unavailable. Domains and contacts associated via' \ - ' organizations are not shown.' - end - - def test_show_direct_domains_when_company_register_is_unavailable - assert_equal 'US-1234', @user.registrant_ident - - contact = contacts(:john) - assert_equal '1234', contact.ident - assert_equal Contact::PRIV, contact.ident_type - assert_equal 'US', contact.ident_country_code - - assert_equal contact.becomes(Registrant), @domain.registrant - assert_equal 'shop.test', @domain.name - - CompanyRegister::Client.stub(:new, CompanyRegisterClientStub.new) do - visit registrant_domains_url - end - - assert_text 'shop.test' - end -end diff --git a/test/system/registrant_area/domains_test.rb b/test/system/registrant_area/domains_test.rb deleted file mode 100644 index fa151c89e..000000000 --- a/test/system/registrant_area/domains_test.rb +++ /dev/null @@ -1,22 +0,0 @@ -require 'application_system_test_case' - -class RegistrantDomainsTest < ApplicationSystemTestCase - setup do - sign_in users(:registrant) - end - - def test_shows_domains_where_current_user_is_registrant - visit registrant_domains_url - assert_text 'shop.test' - end - - def test_shows_domains_where_current_user_is_contact_person - visit registrant_domains_url - assert_text 'airport.test' - end - - def test_shows_domains_where_current_user_has_associated_organizations - visit registrant_domains_url - assert_text 'library.test' - end -end diff --git a/test/system/registrant_area/layout_test.rb b/test/system/registrant_area/layout_test.rb deleted file mode 100644 index 9df8028e3..000000000 --- a/test/system/registrant_area/layout_test.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'application_system_test_case' - -class RegistrantLayoutTest < ApplicationSystemTestCase - def setup - super - sign_in(users(:registrant)) - end - - def test_has_link_to_rest_whois_and_internet_ee - visit registrant_domains_url - - assert(has_link?('Internet.ee', href: 'https://internet.ee')) - assert(has_link?('WHOIS', href: 'https://whois.internet.ee')) - end -end diff --git a/test/system/registrant_area/tara/tara_users_test.rb b/test/system/registrant_area/tara/tara_users_test.rb deleted file mode 100644 index 5020616d4..000000000 --- a/test/system/registrant_area/tara/tara_users_test.rb +++ /dev/null @@ -1,51 +0,0 @@ -require 'application_system_test_case' - -class RegistrantAreaTaraUsersTest < ApplicationSystemTestCase - def setup - super - - OmniAuth.config.test_mode = true - @registrant = users(:registrant) - - @existing_user_hash = { - 'provider' => 'rant_tara', - 'uid' => "US1234", - 'info': { 'first_name': 'Registrant', 'last_name': 'User' } - } - - @new_user_hash = { - 'provider' => 'rant_tara', - 'uid' => 'EE51007050604', - 'info': { 'first_name': 'New Registrant', 'last_name': 'User'} - } - end - - def teardown - super - - OmniAuth.config.test_mode = false - OmniAuth.config.mock_auth['rant_tara'] = nil - end - - def test_existing_user_gets_signed_in - OmniAuth.config.mock_auth[:rant_tara] = OmniAuth::AuthHash.new(@existing_user_hash) - - visit new_registrant_user_session_path - click_link('Sign in') - - assert_text('Signed in successfully') - end - - def test_new_user_is_created_and_signed_in - OmniAuth.config.mock_auth[:rant_tara] = OmniAuth::AuthHash.new(@new_user_hash) - - assert_difference 'RegistrantUser.count' do - visit new_registrant_user_session_path - click_link('Sign in') - - assert_equal 'New Registrant User', RegistrantUser.last.username - assert_equal 'EE-51007050604', RegistrantUser.last.registrant_ident - assert_text('Signed in successfully') - end - end -end diff --git a/test/system/registrar_area/account_activities_test.rb b/test/system/registrar_area/account_activities_test.rb new file mode 100644 index 000000000..1944dc2fb --- /dev/null +++ b/test/system/registrar_area/account_activities_test.rb @@ -0,0 +1,28 @@ +require 'application_system_test_case' + +class RegistrarAccountActivitiesTest < ApplicationSystemTestCase + setup do + @registrar = registrars(:bestnames) + sign_in users(:api_bestnames) + end + + def test_show_account_activity_page + account_activities(:one).update(sum: "123.00") + visit registrar_account_activities_path + assert_text 'Account activity' + end + + def test_download_account_activity + now = Time.zone.parse('2010-07-05 08:00') + travel_to now + account_activities(:one).update(sum: "123.00") + + get registrar_account_activities_path(format: :csv) + + assert_response :ok + assert_equal "text/csv", response.headers['Content-Type'] + assert_equal %(attachment; filename="account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv"; filename*=UTF-8''account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv), + response.headers['Content-Disposition'] + assert_not_empty response.body + end +end \ No newline at end of file diff --git a/test/system/registrar_area/bulk_change/admin_contact_test.rb b/test/system/registrar_area/bulk_change/admin_contact_test.rb new file mode 100644 index 000000000..8847812cb --- /dev/null +++ b/test/system/registrar_area/bulk_change/admin_contact_test.rb @@ -0,0 +1,49 @@ +require 'application_system_test_case' + +class RegistrarAreaAdminContactBulkChangeTest < ApplicationSystemTestCase + setup do + sign_in users(:api_bestnames) + end + + def test_replace_domain_contacts_of_current_registrar + request_stub = stub_request(:patch, /domains\/admin_contacts/) + .with(body: { current_contact_id: 'william-001', new_contact_id: 'john-001' }, + basic_auth: ['test_bestnames', 'testtest']) + .to_return(body: { data: { affected_domains: %w[foo.test bar.test], + skipped_domains: %w[baz.test qux.test] } }.to_json, + status: 200) + + visit registrar_domains_url + click_link 'Bulk change' + click_link 'Admin contact' + + find('.current_admin_contact').fill_in 'Current contact ID', with: 'william-001' + find('.new_admin_contact').fill_in 'New contact ID', with: 'john-001' + click_on 'Replace admin contacts' + + assert_requested request_stub + assert_current_path registrar_domains_path + assert_text 'Admin contacts have been successfully replaced' + assert_text 'Affected domains: foo.test, bar.test' + assert_text 'Skipped domains: baz.test, qux.test' + end + + def test_fails_gracefully + stub_request(:patch, /domains\/admin_contacts/) + .to_return(status: 400, + body: { message: 'epic fail' }.to_json, + headers: { 'Content-type' => Mime[:json] }) + + visit registrar_domains_url + click_link 'Bulk change' + click_link 'Admin contact' + + find('.current_admin_contact').fill_in 'Current contact ID', with: 'william-001' + find('.new_admin_contact').fill_in 'New contact ID', with: 'john-001' + click_on 'Replace admin contacts' + + assert_text 'epic fail' + assert_field 'Current contact ID', with: 'william-001' + assert_field 'New contact ID', with: 'john-001' + end +end diff --git a/test/system/registrar_area/bulk_change/tech_contact_test.rb b/test/system/registrar_area/bulk_change/tech_contact_test.rb index e08457f60..055ec25ca 100644 --- a/test/system/registrar_area/bulk_change/tech_contact_test.rb +++ b/test/system/registrar_area/bulk_change/tech_contact_test.rb @@ -16,8 +16,8 @@ class RegistrarAreaTechContactBulkChangeTest < ApplicationSystemTestCase visit registrar_domains_url click_link 'Bulk change' - fill_in 'Current contact ID', with: 'william-001' - fill_in 'New contact ID', with: 'john-001' + find('.current_tech_contact').fill_in 'Current contact ID', with: 'william-001' + find('.new_tech_contact').fill_in 'New contact ID', with: 'john-001' click_on 'Replace technical contacts' assert_requested request_stub @@ -36,8 +36,8 @@ class RegistrarAreaTechContactBulkChangeTest < ApplicationSystemTestCase visit registrar_domains_url click_link 'Bulk change' - fill_in 'Current contact ID', with: 'william-001' - fill_in 'New contact ID', with: 'john-001' + find('.current_tech_contact').fill_in 'Current contact ID', with: 'william-001' + find('.new_tech_contact').fill_in 'New contact ID', with: 'john-001' click_on 'Replace technical contacts' assert_text 'epic fail' diff --git a/test/system/registrar_area/tara/tara_users_test.rb b/test/system/registrar_area/tara/tara_users_test.rb index a2defd715..005504043 100644 --- a/test/system/registrar_area/tara/tara_users_test.rb +++ b/test/system/registrar_area/tara/tara_users_test.rb @@ -34,6 +34,18 @@ class TaraUsersTest < ApplicationSystemTestCase assert_text('Signed in successfully') end + def test_existing_user_logs_in_without_cookie_overflow + @existing_user_hash['credentials'] = massive_hash + OmniAuth.config.mock_auth[:tara] = OmniAuth::AuthHash.new(@existing_user_hash) + + visit new_registrar_user_session_path + assert_nothing_raised do + click_link('Sign in') + end + + assert_text('Signed in successfully') + end + def test_nonexisting_user_gets_error_message OmniAuth.config.mock_auth[:tara] = OmniAuth::AuthHash.new(@new_user_hash) @@ -42,4 +54,10 @@ class TaraUsersTest < ApplicationSystemTestCase assert_text('No such user') end + + def massive_hash + o = [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten + string = (0...5000).map { o[rand(o.length)] }.join + {"access_token":"AT-540-Fj5gbPvJp4jPkO-4EdgzIhIhhJapoRTM","token_type":"bearer","expires_in":600,"id_token":string} + end end diff --git a/test/tasks/contacts/archive_test.rb b/test/tasks/contacts/archive_test.rb index eebfa7b68..f5ecff092 100644 --- a/test/tasks/contacts/archive_test.rb +++ b/test/tasks/contacts/archive_test.rb @@ -14,7 +14,7 @@ class ArchiveContactsTaskTest < ActiveSupport::TestCase def archivable_contact contact = contacts(:john) Setting.orphans_contacts_in_months = 0 - DomainVersion.delete_all + Version::DomainVersion.delete_all other_contact = contacts(:william) assert_not_equal other_contact, contact diff --git a/test/test_helper.rb b/test/test_helper.rb index a1634f717..fe20f7a6e 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -42,7 +42,7 @@ EInvoice.provider = EInvoice::Providers::TestProvider.new class ActiveSupport::TestCase ActiveRecord::Migration.check_pending! fixtures :all - set_fixture_class log_domains: DomainVersion + set_fixture_class log_domains: Version::DomainVersion teardown do travel_back
    + <%= sort_link(@q, 'description') %> @@ -26,6 +26,9 @@ <%= sort_link(@q, 'sum') %> + <%= sort_link(@q, 'new_balance', 'New balance') %> +
    <%= s %> + <%= x.new_balance.present? ? "#{currency(x.new_balance)} EUR" : 'N/A' %> +