diff --git a/.codeclimate.yml b/.codeclimate.yml index 9df308022..be8f1df7a 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -23,6 +23,7 @@ exclude_patterns: - "bin/" - "config/" - "db/" + - "lib/" - "vendor/" - "test/" - "spec/" diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fe8f891a..838ff6ea4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,40 @@ +10.07.2018 +* Nameserver bulk change returns list of affected doamins [#835](https://github.com/internetee/registry/issues/835) + +26.06.2018 +* Whois data is updated now on pendingUpdate status removal [#757](https://github.com/internetee/registry/issues/757) +* Portal for registrars displays control code for MID authentication [#893](https://github.com/internetee/registry/issues/893) +* Changed date format in Directo invoice XML [#890](https://github.com/internetee/registry/pull/890) +* Registrant portal UI improvements [#888](https://github.com/internetee/registry/issues/888) +* Removed unused mailer code [#882](https://github.com/internetee/registry/pull/882) +* Sprocets gem update to 3.7.2 [#892](https://github.com/internetee/registry/issues/892) +* Replased Warden test helpers with Devise [#889](https://github.com/internetee/registry/issues/889) +* Removed dev rake task [#872](https://github.com/internetee/registry/pull/872) +* Spring gem removed [#856](https://github.com/internetee/registry/issues/856) +* Dcker conf changes [#881](https://github.com/internetee/registry/pull/881) +* Fixed Estonia in the country drop-down [#877](https://github.com/internetee/registry/issues/877) +* Codeclimate conf improvements [#854](https://github.com/internetee/registry/pull/854) +* Removed codeclimate badge from README [#876](https://github.com/internetee/registry/issues/876) +* added UUID for contact objects [#873](https://github.com/internetee/registry/pull/873) +* backported Rails 5 API [#868](https://github.com/internetee/registry/issues/868) + +20.06.2018 +* Bulk change function for technical contact replacement [#662](https://github.com/internetee/registry/issues/662) +* Removed vatcode and totalvat elements from directo request in attempt to fix invoice sending issue [#844](https://github.com/internetee/registry/issues/844) +* Regsitrar: added credit card payment option - disabled at the moment due to contractual reaons [#419](https://github.com/internetee/registry/issues/419) +* Registrant: enabled WHOIS requests over RestWHOIS API [#852](https://github.com/internetee/registry/issues/852) +* Fixed rspec configuration that caused test failures [#858](https://github.com/internetee/registry/issues/858) +* Admin: refactored date selection in pricelist [#869](https://github.com/internetee/registry/issues/869) +* Added uglifier gem for es6 compression [#864](https://github.com/internetee/registry/issues/864) +* Removed lib folder from autoload path [#859](https://github.com/internetee/registry/issues/859) +* test environment config improvements [#860](https://github.com/internetee/registry/issues/860) +* translation fixes [#865](https://github.com/internetee/registry/issues/865) +* removed obsolete .agignore [#866](https://github.com/internetee/registry/issues/866) +* removed rubocop gem [#857](https://github.com/internetee/registry/issues/857) +* new invoice payment test fix [#863](https://github.com/internetee/registry/issues/863) +* get puma gem config from Rails 5 [#867](https://github.com/internetee/registry/issues/867) +* Rails5 API controller temporary backport [#868](https://github.com/internetee/registry/issues/868) + 25.05.2018 * GDPR: updated whois templates with configurable disclaimer [#795](https://github.com/internetee/registry/issues/795) * GDPR: email forwarding solution to contact private domain registrants without revealing their email addresses [#824](https://github.com/internetee/registry/issues/824) diff --git a/Dockerfile b/Dockerfile index 480231fc2..bd0cbc07b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,9 @@ -FROM ruby:2.3 +FROM internetee/ruby:2.3 MAINTAINER maciej.szlosarczyk@internet.ee -RUN apt-get update > /dev/null && apt-get install -y > /dev/null \ - build-essential \ - nodejs \ - imagemagick \ - postgresql-client - -RUN apt-get install -y > /dev/null \ - qt5-default \ - libqt5webkit5-dev \ - gstreamer1.0-plugins-base \ - gstreamer1.0-tools \ - qtdeclarative5-dev \ - gstreamer1.0-x - RUN mkdir -p /opt/webapps/app/tmp/pids WORKDIR /opt/webapps/app - COPY Gemfile Gemfile.lock ./ RUN gem install bundler && bundle install --jobs 20 --retry 5 + EXPOSE 3000 diff --git a/Gemfile b/Gemfile index 4073bd1e5..7682cdc4e 100644 --- a/Gemfile +++ b/Gemfile @@ -102,9 +102,6 @@ gem 'jquery-ui-rails', '5.0.5' gem 'active_model-errors_details' # Backport from Rails 5, https://github.com/rails/rails/pull/18322 group :development do - gem 'spring' - gem 'spring-commands-rspec' - # deploy gem 'mina', '0.3.1' # for fast deployment gem 'puma' @@ -120,10 +117,6 @@ group :development, :test do gem 'pry', '0.10.1' gem 'bullet', '4.14.7' # for finding database optimizations - gem 'bundler-audit' - gem 'brakeman', '3.6.1', require: false # for security audit' - # tmp, otherwise conflics with breakman - # gem 'html2haml', github: 'haml/html2haml', ref: '6984f50bdbbd6291535027726a5697f28778ee8d' gem 'html2haml', '2.1.0' gem 'sdoc', '0.4.1' # bundle exec rake doc:rails generates the API under doc/api. gem 'railroady', '1.3.0' # to generate database diagrams diff --git a/Gemfile.lock b/Gemfile.lock index de4749bd0..9a88e782b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -122,14 +122,10 @@ GEM bootstrap-sass (3.3.5.1) autoprefixer-rails (>= 5.0.0.1) sass (>= 3.3.0) - brakeman (3.6.1) builder (3.2.3) bullet (4.14.7) activesupport (>= 3.0.0) uniform_notifier (~> 1.9.0) - bundler-audit (0.5.0) - bundler (~> 1.2) - thor (~> 0.18) cancancan (1.11.0) capybara (2.14.0) addressable @@ -297,7 +293,7 @@ GEM erubis que (~> 0.8) sinatra - rack (1.6.9) + rack (1.6.10) rack-accept (0.4.5) rack (>= 0.4) rack-mount (0.8.3) @@ -408,11 +404,7 @@ GEM sixarm_ruby_unaccent (1.1.1) slop (3.6.0) socksify (1.7.1) - spring (2.0.2) - activesupport (>= 4.2) - spring-commands-rspec (1.0.4) - spring (>= 0.9.1) - sprockets (3.7.1) + sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) sprockets-rails (3.2.1) @@ -466,9 +458,7 @@ DEPENDENCIES airbrake autodoc bootstrap-sass (= 3.3.5.1) - brakeman (= 3.6.1) bullet (= 4.14.7) - bundler-audit cancancan (= 1.11.0) capybara coderay (= 1.1.0) @@ -519,8 +509,6 @@ DEPENDENCIES selectize-rails (= 0.12.1) simplecov simpleidn (= 0.0.7) - spring - spring-commands-rspec uglifier uuidtools (= 2.1.5) validates_email_format_of (= 1.6.3) @@ -528,4 +516,4 @@ DEPENDENCIES whenever (= 0.9.4) BUNDLED WITH - 1.16.1 + 1.16.2 diff --git a/README.md b/README.md index a8a85a3d8..5beca0a87 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ Domain Registry =============== [![Build Status](https://travis-ci.org/internetee/registry.svg?branch=master)](https://travis-ci.org/internetee/registry) [![Code Climate](https://codeclimate.com/github/internetee/registry/badges/gpa.svg)](https://codeclimate.com/github/internetee/registry) -[![Issue Count](https://codeclimate.com/github/internetee/registry/badges/issue_count.svg)](https://codeclimate.com/github/internetee/registry) [![Test Coverage](https://codeclimate.com/github/internetee/registry/badges/coverage.svg)](https://codeclimate.com/github/internetee/registry/coverage) [![Documentation Status](https://readthedocs.org/projects/eeregistry/badge/?version=latest)](http://docs.internet.ee/en/latest/?badge=latest) @@ -31,7 +30,7 @@ Documentation Installation ------------ -### Registry app +### Registry app Registry based on Rails 4 installation (rbenv install is under Debian build doc) @@ -57,7 +56,7 @@ Manual demo install and database setup: tar -xzvf mod_epp-1.10.tar.gz cd mod_epp-1.10 -Patch mod_epp for Rack. Beacause Rack multipart parser expects specifically +Patch mod_epp for Rack. Beacause Rack multipart parser expects specifically formatted content boundaries, the mod_epp needs to be modified before building: wget https://github.com/internetee/registry/raw/master/doc/patches/mod_epp_1.10-rack-friendly.patch @@ -136,7 +135,7 @@ For Apache, registry admin goes to port 443 in production, /etc/apache2/sites-en ``` -Registrar configuration (/etc/apache2/sites-enabled/registrar.conf) is as follows: +Registrar configuration (/etc/apache2/sites-enabled/registrar.conf) is as follows: ``` ServerName your-registrar-domain @@ -179,7 +178,7 @@ Registrar configuration (/etc/apache2/sites-enabled/registrar.conf) is as follow # for Apache verison 2.4 or newer # Require all granted - + Options -MultiViews @@ -220,7 +219,7 @@ Registrar configuration (/etc/apache2/sites-enabled/registrar.conf) is as follow ``` -Registrant configuration (/etc/apache2/sites-enabled/registrant.conf) is as follows: +Registrant configuration (/etc/apache2/sites-enabled/registrant.conf) is as follows: ``` ServerName your-registrant-domain @@ -263,7 +262,7 @@ Registrant configuration (/etc/apache2/sites-enabled/registrant.conf) is as foll # for Apache verison 2.4 or newer # Require all granted - + Options -MultiViews @@ -271,11 +270,11 @@ Registrant configuration (/etc/apache2/sites-enabled/registrant.conf) is as foll Allow from none Deny from all - + Allow from all - + Allow from all @@ -342,8 +341,8 @@ For Apache, REPP goes to port 443 in production, /etc/apache2/sites-enabled/repp ``` -For Apache, epp goes to port 700. -Be sure to update paths to match your system configuration. +For Apache, epp goes to port 700. +Be sure to update paths to match your system configuration. /etc/apache2/sites-enabled/epp.conf short example: ```apache @@ -405,7 +404,7 @@ Be sure to update paths to match your system configuration. EPPSessionRoot /proxy/session EPPErrorRoot /proxy/error EPPRawFrame raw_frame - + ProxyPass /proxy/ http://localhost:8080/epp/ EPPAuthURI implicit @@ -421,7 +420,7 @@ Enable epp_ssl and restart apache Now you should see registry admin at https://your-domain -All registry demo data can be found at: +All registry demo data can be found at: db/seeds.rb @@ -464,4 +463,3 @@ Please follow EPP web client readme: Please follow WHOIS server readme: https://github.com/internetee/whois - diff --git a/app/api/repp/nameservers_v1.rb b/app/api/repp/nameservers_v1.rb index d653adf7f..04d7d4f6a 100644 --- a/app/api/repp/nameservers_v1.rb +++ b/app/api/repp/nameservers_v1.rb @@ -29,7 +29,7 @@ module Repp } begin - current_user.registrar.replace_nameservers(hostname, new_attributes) + affected_domains = current_user.registrar.replace_nameservers(hostname, new_attributes) rescue ActiveRecord::RecordInvalid => e error!({ errors: e.record.errors.full_messages.map { |error| { title: error } } }, 400) end @@ -37,7 +37,8 @@ module Repp status 200 @response = { data: { type: 'nameserver', id: params[:data][:attributes][:hostname], - attributes: params[:data][:attributes] } } + attributes: params[:data][:attributes] }, + affected_domains: affected_domains } end end end diff --git a/app/assets/stylesheets/shared/general.sass b/app/assets/stylesheets/shared/general.sass index fd8bc2905..07b92cdbe 100644 --- a/app/assets/stylesheets/shared/general.sass +++ b/app/assets/stylesheets/shared/general.sass @@ -52,10 +52,5 @@ body > .container .text-grey color: grey -.partially-hidden - border: 1px solid #dddddd - padding-left: 4px - padding-right: 4px - .disabled-value padding-top: 8px diff --git a/app/controllers/registrant/contacts_controller.rb b/app/controllers/registrant/contacts_controller.rb index 948bc1a94..5b1c8db72 100644 --- a/app/controllers/registrant/contacts_controller.rb +++ b/app/controllers/registrant/contacts_controller.rb @@ -1,11 +1,14 @@ class Registrant::ContactsController < RegistrantController helper_method :domain_ids + def show - @contact = Contact.where(id: contacts).find_by(id: params[:id]) + @contact = Contact.where(id: contacts).find_by(id: params[:id]) authorize! :read, @contact end + private + def contacts begin DomainContact.where(domain_id: domain_ids).pluck(:contact_id) | Domain.where(id: domain_ids).pluck(:registrant_id) diff --git a/app/controllers/registrant/domain_update_confirms_controller.rb b/app/controllers/registrant/domain_update_confirms_controller.rb index feaa39d6e..8c91db6ac 100644 --- a/app/controllers/registrant/domain_update_confirms_controller.rb +++ b/app/controllers/registrant/domain_update_confirms_controller.rb @@ -1,6 +1,6 @@ class Registrant::DomainUpdateConfirmsController < RegistrantController - skip_before_action :authenticate_user!, only: [:show, :update] - skip_authorization_check only: [:show, :update] + skip_before_action :authenticate_user!, only: %i[show update] + skip_authorization_check only: %i[show update] def show return if params[:confirmed] || params[:rejected] diff --git a/app/controllers/registrant/registrars_controller.rb b/app/controllers/registrant/registrars_controller.rb index d0630b73a..7bb101bb9 100644 --- a/app/controllers/registrant/registrars_controller.rb +++ b/app/controllers/registrant/registrars_controller.rb @@ -1,7 +1,6 @@ class Registrant::RegistrarsController < RegistrantController - def show @registrar = Registrar.find(params[:id]) authorize! :read, @registrar end -end +end \ No newline at end of file diff --git a/app/controllers/registrar/nameservers_controller.rb b/app/controllers/registrar/nameservers_controller.rb index 90dd5afb4..31a047d2f 100644 --- a/app/controllers/registrar/nameservers_controller.rb +++ b/app/controllers/registrar/nameservers_controller.rb @@ -44,7 +44,10 @@ class Registrar parsed_response = JSON.parse(response.body, symbolize_names: true) if response.code == '200' - flash[:notice] = t '.replaced' + notices = [t('.replaced')] + notices << "#{t('.affected_domains')}: #{parsed_response[:affected_domains].join(', ')}" + + flash[:notice] = notices redirect_to registrar_domains_url else @api_errors = parsed_response[:errors] diff --git a/app/jobs/domain_update_confirm_job.rb b/app/jobs/domain_update_confirm_job.rb index b4d2a9f57..c661c7b6b 100644 --- a/app/jobs/domain_update_confirm_job.rb +++ b/app/jobs/domain_update_confirm_job.rb @@ -23,7 +23,9 @@ class DomainUpdateConfirmJob < Que::Job registrant: domain.registrant).deliver_now domain.poll_message!(:poll_pending_update_rejected_by_registrant) - domain.clean_pendings_lowlevel + + domain.preclean_pendings + domain.clean_pendings! end destroy # it's best to destroy the job in the same transaction end diff --git a/app/mailers/domain_mailer.rb b/app/mailers/domain_mailer.rb index f14f4b4a7..d92e79ac0 100644 --- a/app/mailers/domain_mailer.rb +++ b/app/mailers/domain_mailer.rb @@ -45,18 +45,4 @@ class DomainMailer < ApplicationMailer subject: "#{I18n.t(:delete_confirmation_subject, name: @domain.name)} [#{@domain.name}]") end - - private - # app/models/DomainMailModel provides the data for mail that can be composed_from - # which ensures that values of objects are captured when they are valid, not later when this method is executed - def compose_from(params) - @params = params - return if delivery_off?(params, params[:deliver_emails]) - return if whitelist_blocked?(params[:recipient]) - params[:errors].map do |error| - logger.warn error - return - end - mail(to: params[:recipient], subject: params[:subject]) - end -end +end \ No newline at end of file diff --git a/app/models/concerns/contact/transferable.rb b/app/models/concerns/contact/transferable.rb index 14c1cac3c..3f151251a 100644 --- a/app/models/concerns/contact/transferable.rb +++ b/app/models/concerns/contact/transferable.rb @@ -16,6 +16,7 @@ module Concerns::Contact::Transferable new_contact.regenerate_code new_contact.regenerate_auth_info new_contact.remove_address unless self.class.address_processing? + new_contact.uuid = nil new_contact.save(validate: false) new_contact end diff --git a/app/models/contact.rb b/app/models/contact.rb index 24dc2b4f2..088ec0b59 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -447,31 +447,6 @@ class Contact < ActiveRecord::Base domains end - def all_registrant_domains(page: nil, per: nil, params: {}, registrant: nil) - - if registrant - sorts = params.fetch(:sort, {}).first || [] - sort = Domain.column_names.include?(sorts.first) ? sorts.first : "valid_to" - order = {"asc"=>"desc", "desc"=>"asc"}[sorts.second] || "desc" - - domain_ids = DomainContact.distinct.where(contact_id: registrant.id).pluck(:domain_id) - - domains = Domain.where(id: domain_ids).includes(:registrar).page(page).per(per) - if sorts.first == "registrar_name".freeze - domains = domains.includes(:registrar).where.not(registrars: {id: nil}).order("registrars.name #{order} NULLS LAST") - else - domains = domains.order("#{sort} #{order} NULLS LAST") - end - - domain_c = Hash.new([]) - registrant_domains.where(id: domains.map(&:id)).each{|d| domain_c[d.id] |= ["Registrant".freeze] } - DomainContact.where(contact_id: id, domain_id: domains.map(&:id)).each{|d| domain_c[d.domain_id] |= [d.type] } - domains.each{|d| d.roles = domain_c[d.id].uniq} - domains - end - end - - def update_prohibited? (statuses & [ CLIENT_UPDATE_PROHIBITED, diff --git a/app/models/directo.rb b/app/models/directo.rb index 1269e7033..3fc51bb40 100644 --- a/app/models/directo.rb +++ b/app/models/directo.rb @@ -26,7 +26,7 @@ class Directo < ActiveRecord::Base xml.invoice( "SalesAgent" => Setting.directo_sales_agent, "Number" => num, - "InvoiceDate" => invoice.created_at.strftime("%Y-%m-%dT%H:%M:%S"), + "InvoiceDate" => invoice.created_at.strftime("%Y-%m-%d"), "PaymentTerm" => Setting.directo_receipt_payment_term, "Currency" => invoice.currency, "CustomerCode"=> invoice.buyer.accounting_customer_code diff --git a/app/models/domain.rb b/app/models/domain.rb index 3fc3bf0d6..30ed0b580 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -294,36 +294,6 @@ class Domain < ActiveRecord::Base save end - - # state changes may be done low-level - no validation - # in this metod we still save PaperTrail log. - def clean_pendings_lowlevel - statuses.delete(DomainStatus::PENDING_DELETE_CONFIRMATION) - statuses.delete(DomainStatus::PENDING_UPDATE) - statuses.delete(DomainStatus::PENDING_DELETE) - - status_notes[DomainStatus::PENDING_UPDATE] = '' - status_notes[DomainStatus::PENDING_DELETE] = '' - - hash = { - registrant_verification_token: nil, - registrant_verification_asked_at: nil, - pending_json: {}, - status_notes: status_notes, - statuses: statuses.presence || [DomainStatus::OK], - # need this column in order to update PaperTrail version properly - updated_at: Time.now.utc - } - - # PaperTrail - self.attributes = hash - record_update - clear_version_instance! - reset_transaction_id - - update_columns(hash) - end - def pending_update! return true if pending_update? self.epp_pending_update = true # for epp @@ -581,10 +551,6 @@ class Domain < ActiveRecord::Base end end - def send_mail(action) - DomainMailer.send(action, DomainMailModel.new(self).send(action)).deliver - end - def admin_contact_names admin_contacts.names end diff --git a/app/models/domain_cron.rb b/app/models/domain_cron.rb index 80bf32c5a..8de52b226 100644 --- a/app/models/domain_cron.rb +++ b/app/models/domain_cron.rb @@ -21,7 +21,10 @@ class DomainCron if domain.pending_delete? || domain.pending_delete_confirmation? DomainMailer.pending_delete_expired_notification(domain.id, true).deliver end - domain.clean_pendings_lowlevel + + domain.preclean_pendings + domain.clean_pendings! + unless Rails.env.test? STDOUT << "#{Time.zone.now.utc} DomainCron.clean_expired_pendings: ##{domain.id} (#{domain.name})\n" end diff --git a/app/models/domain_mail_model.rb b/app/models/domain_mail_model.rb deleted file mode 100644 index 3f92a3138..000000000 --- a/app/models/domain_mail_model.rb +++ /dev/null @@ -1,117 +0,0 @@ -class DomainMailModel - # Capture current values used in app/views/mailers/domain_mailer/* and app/mailers/domain_mailer will send later - - def initialize(domain) - @domain = domain - @params = {errors: [], deliver_emails: domain.deliver_emails, id: domain.id} - end - - def pending_delete_rejected_notification - registrant - subject(:pending_delete_rejected_notification_subject) - compose - end - - def pending_delete_expired_notification - registrant - subject(:pending_delete_expired_notification_subject) - compose - end - - def delete_confirmation - registrant - subject(:delete_confirmation_subject) - compose - end - - def force_delete - admins - subject(:force_delete_subject) - compose - end - - private - - def registrant_old - @params[:recipient] = format Registrant.find(@domain.registrant_id_was).email - end - - def registrant - @params[:recipient] = format @domain.registrant.email - end - - def registrant_pending - @params[:recipient] = format @domain.pending_json['new_registrant_email'] - @params[:new_registrant_name] = @domain.pending_json['new_registrant_name'] - @params[:old_registrant_name] = @domain.registrant.name - end - - # registrant and domain admin contacts - def admins - emails = ([@domain.registrant.email] + @domain.admin_contacts.map { |x| format(x.email) }) - @params[:recipient] = emails.uniq.map { |x| format(x) } - end - - # puny internet domain name, TODO: username - def format(email) - return warn_no_email if email.nil? - user, host = email.split('@') - host = SimpleIDN.to_ascii(host) - "#{user}@#{host}" - end - - def subject(subject) - @params[:name] = @domain.name - @params[:subject] = "#{I18n.t(subject, name: @domain.name)}, [#{@domain.name}]" - end - - def confirm_update - verification_url('domain_update_confirms') - end - - def compose - @params - end - - def verification_url(path) - token = verification_token or return - @params[:verification_url] = "#{ENV['registrant_url']}/registrant/#{path}/#{@domain.id}?token=#{token}" - end - - def verification_token - return warn_missing(:registrant_verification_token) if @domain.registrant_verification_token.blank? - return warn_missing(:registrant_verification_asked_at) if @domain.registrant_verification_asked_at.blank? - @domain.registrant_verification_token - end - - def domain_info - [:name, :registrar_name, - :registrant_name, :registrant_ident, :registrant_email, - :registrant_street,:registrant_city - ].each do |attr| - @params.store attr, @domain.send(attr) - end - @params.store :registrant_country, @domain.registrant_country.name - @params.store :registrant_priv, @domain.registrant.priv? - @params.store :old_registrant_name, Registrant.find(@domain.registrant_id_was).name - @params - end - - def warn_no_email(item = 'email') - warn_missing item - nil - end - - def warn_missing(item) - warn_not_delivered "#{item.to_s} is missing for #{@domain.name}" - end - - def warn_not_delivered(reason) - message = "EMAIL NOT DELIVERED: #{reason}" - @params[:errors] << message -# Rails.logger.warn message - nil - end - -end - diff --git a/app/models/registrar.rb b/app/models/registrar.rb index 05a5ad380..de02d42a7 100644 --- a/app/models/registrar.rb +++ b/app/models/registrar.rb @@ -132,14 +132,20 @@ class Registrar < ActiveRecord::Base # Audit log is needed, therefore no raw SQL def replace_nameservers(hostname, new_attributes) transaction do + domain_list = [] + nameservers.where(hostname: hostname).find_each do |original_nameserver| new_nameserver = Nameserver.new new_nameserver.domain = original_nameserver.domain new_nameserver.attributes = new_attributes new_nameserver.save! + domain_list << original_nameserver.domain.name + original_nameserver.destroy! end + + domain_list.uniq.sort end end diff --git a/app/models/sorted_country.rb b/app/models/sorted_country.rb index 19ad5f4f3..7b27adacb 100644 --- a/app/models/sorted_country.rb +++ b/app/models/sorted_country.rb @@ -18,7 +18,7 @@ class SortedCountry def quick_list @quick_list ||= [ - %w[Estonia' EE], + %w[Estonia EE], %w[Finland FI], %w[Latvia LV], %w[Lithuania LT], diff --git a/app/views/admin/contacts/partials/_general.haml b/app/views/admin/contacts/partials/_general.haml index db1eaf412..029f89509 100644 --- a/app/views/admin/contacts/partials/_general.haml +++ b/app/views/admin/contacts/partials/_general.haml @@ -6,9 +6,10 @@ %dt= t(:id) %dd= @contact.code - %dt= t(:authinfo_pw) + %dt= Contact.human_attribute_name :auth_info %dd - = text_field_tag :auth_info, @contact.auth_info, readonly: true, class: 'partially-hidden' + = tag :input, type: 'text', value: @contact.auth_info, readonly: true, + class: 'form-control input-sm' %br diff --git a/app/views/application/_flash_messages.html.erb b/app/views/application/_flash_messages.html.erb index 9b31f0d3f..364e3e5ca 100644 --- a/app/views/application/_flash_messages.html.erb +++ b/app/views/application/_flash_messages.html.erb @@ -1,24 +1,8 @@ -<% if flash[:notice] %> -
- - <% if flash[:notice].respond_to?(:join) %> -

<%= flash[:notice].join('
').html_safe %>

- <% else %> -

<%= flash[:notice] %>

- <% end %> +<% display = (flash[:notice] || flash[:alert] || flash[:warning]) ? 'block' : 'none' %> +
+ <% type = (flash[:notice]) ? 'bg-success' : 'bg-danger' %> + <% type = 'bg-warning' if flash[:warning] %> +
+ <%= flash[:notice] || flash[:alert] || flash[:warning] %>
-<% end %> - -<% if flash[:alert] %> -
- -

<%= flash[:alert] %>

-
-<% end %> - -<% if flash[:info] %> -
- -

<%= flash[:info] %>

-
-<% end %> +
diff --git a/app/views/layouts/registrant/application.html.erb b/app/views/layouts/registrant/application.html.erb index 6d47b72cf..4bd099937 100644 --- a/app/views/layouts/registrant/application.html.erb +++ b/app/views/layouts/registrant/application.html.erb @@ -65,7 +65,7 @@
- <%= render 'shared/flash' %> + <%= render 'flash_messages' %> <%= yield %>
diff --git a/app/views/layouts/registrar/base.html.erb b/app/views/layouts/registrar/base.html.erb index 3bc1c5b0f..c14899418 100644 --- a/app/views/layouts/registrar/base.html.erb +++ b/app/views/layouts/registrar/base.html.erb @@ -1,63 +1,63 @@ - - - - <% if content_for? :head_title %> - <%= yield :head_title %> - <% else %> - - <%= t(:registrar_head_title) %> - - <% end %> - <%= csrf_meta_tags %> - <%= stylesheet_link_tag 'registrar-manifest', media: 'all' %> - <%= favicon_link_tag 'favicon.ico' %> - - - -
- <%= render 'flash_messages' %> - <% if depp_controller? %> - <%= render 'registrar/shared/epp_results' %> - <% end %> - <%= yield %> -
-
-
-
-
- <%= image_tag 'eis-logo-et.png' %> +
+
+
+
+ <%= image_tag 'eis-logo-et.png' %> +
+
+ Version + <%= CURRENT_COMMIT_HASH %> +
+
-
- Version - <%= CURRENT_COMMIT_HASH %> -
-
-
-
-<%= javascript_include_tag 'registrar-manifest', async: true %> - +
+ <%= javascript_include_tag 'registrar-manifest', async: true %> + diff --git a/app/views/layouts/registrar/sessions.html.erb b/app/views/layouts/registrar/sessions.html.erb index 904388155..4632e477c 100644 --- a/app/views/layouts/registrar/sessions.html.erb +++ b/app/views/layouts/registrar/sessions.html.erb @@ -51,4 +51,4 @@ - \ No newline at end of file + diff --git a/app/views/registrant/contacts/partials/_address.haml b/app/views/registrant/contacts/partials/_address.haml deleted file mode 100644 index fe57bd393..000000000 --- a/app/views/registrant/contacts/partials/_address.haml +++ /dev/null @@ -1,23 +0,0 @@ -.panel.panel-default - .panel-heading - %h3.panel-title= t(:address) - .panel-body - %dl.dl-horizontal - - if @contact.org_name.present? - %dt= t(:org_name) - %dd= @contact.org_name - - %dt= t(:street) - %dd= @contact.street - - %dt= t(:city) - %dd= @contact.city - - %dt= t(:zip) - %dd= @contact.zip - - %dt= t(:state) - %dd= @contact.state - - %dt= t(:country) - %dd= @contact.country diff --git a/app/views/registrant/contacts/partials/_domains.haml b/app/views/registrant/contacts/partials/_domains.haml deleted file mode 100644 index 011b9c404..000000000 --- a/app/views/registrant/contacts/partials/_domains.haml +++ /dev/null @@ -1,30 +0,0 @@ -- domains = contact.all_domains(page: params[:domain_page], per: 20, params: params.merge(leave_domains: domain_ids)) -#contacts.panel.panel-default - .panel-heading - .pull-left - = t(:domains) - .pull-right - = form_tag request.path, method: :get do - = select_tag :domain_filter, options_for_select(%w(Registrant AdminDomainContact TechDomainContact), selected: params[:domain_filter]), - include_blank: true, class: 'form-control2 selectize2' - %button.btn.btn-primary - %span.glyphicon.glyphicon-search - .clearfix - - .table-responsive - %table.table.table-hover.table-bordered.table-condensed - %thead - %tr - %th{class: 'col-xs-3'}=custom_sort_link t(:domain_name), :name - %th{class: 'col-xs-3'}=custom_sort_link t(:registrar_name), :registrar_name - %th{class: 'col-xs-3'}=custom_sort_link t(:valid_to), :valid_to - %th{class: 'col-xs-3'}=custom_sort_link Domain.human_attribute_name(:roles), :roles - %tbody - - domains.each do |x| - %tr - %td= link_to(x.name, [:registrant, x]) - %td= link_to(x.registrar, [:registrant, x.registrar]) - %td= l(x.valid_to, format: :short) - %td= x.roles.join(", ") - -= paginate domains, param_name: :domain_page diff --git a/app/views/registrant/contacts/partials/_general.haml b/app/views/registrant/contacts/partials/_general.haml deleted file mode 100644 index 6a59cdfef..000000000 --- a/app/views/registrant/contacts/partials/_general.haml +++ /dev/null @@ -1,48 +0,0 @@ -.panel.panel-default - .panel-heading - %h3.panel-title= t(:general) - .panel-body - %dl.dl-horizontal - %dt= t(:id) - %dd= @contact.code - - %dt= t(:name) - %dd= @contact.name - - %dt= t(:password) - %dd - = text_field_tag :auth_info, @contact.auth_info, readonly: true, class: 'partially-hidden' - - %br - - %dt= t(:ident) - %dd= ident_for(@contact) - - %dt= t(:email) - %dd= @contact.email - - %dt= t(:phone) - %dd= @contact.phone - - - if @contact.fax - %dt= t(:fax) - %dd= @contact.fax - - %br - - %dt= Contact.human_attribute_name :created_at - %dd - = l(@contact.created_at, format: :short) - by - = @contact.name - - %dt= Contact.human_attribute_name :updated_at - %dd - = l(@contact.updated_at, format: :short) - by - = @contact.name - - %dt= t(:registrar_name) - %dd - - if @contact.registrar.present? - = link_to(@contact.registrar, registrant_registrar_path(@contact.registrar)) diff --git a/app/views/registrant/contacts/partials/_search.haml b/app/views/registrant/contacts/partials/_search.haml deleted file mode 100644 index 4a723bf6b..000000000 --- a/app/views/registrant/contacts/partials/_search.haml +++ /dev/null @@ -1,6 +0,0 @@ -= search_form_for [:registrant, @q] do |f| - = f.search_field :name_cont - = f.submit do - %span.glyphicon.glyphicon-search - - diff --git a/app/views/registrant/contacts/partials/_statuses.haml b/app/views/registrant/contacts/partials/_statuses.haml deleted file mode 100644 index c39075754..000000000 --- a/app/views/registrant/contacts/partials/_statuses.haml +++ /dev/null @@ -1,21 +0,0 @@ -- panel_class = contact.errors.messages[:statuses] ? 'panel-danger' : 'panel-default' -#contact_statuses.panel{class: panel_class} - .panel-heading.clearfix - = t(:statuses) - .table-responsive - %table.table.table-hover.table-bordered.table-condensed - %thead - %tr - %th{class: 'col-xs-6'}= t(:status) - %th{class: 'col-xs-6'}= t(:notes) - %tbody - - contact.statuses.each do |status| - %tr - %td= status - %td= contact.status_notes[status] - - - if contact.errors.messages[:statuses] - %tfoot - - @domain.errors.messages[:statuses].each do |s| - %tr - %td{colspan: 4}= s diff --git a/app/views/registrant/contacts/show.haml b/app/views/registrant/contacts/show.haml deleted file mode 100644 index 521a8d549..000000000 --- a/app/views/registrant/contacts/show.haml +++ /dev/null @@ -1,11 +0,0 @@ -= render 'shared/title', name: @contact.name - -.row - .col-md-6= render 'registrant/contacts/partials/general' - .col-md-6= render 'registrant/contacts/partials/address' -.row - .col-md-12= render 'registrant/contacts/partials/statuses', contact: @contact -.row - .col-md-12= render 'registrant/contacts/partials/domains', contact: @contact - - diff --git a/app/views/registrant/contacts/show.html.erb b/app/views/registrant/contacts/show.html.erb new file mode 100644 index 000000000..6d08feccc --- /dev/null +++ b/app/views/registrant/contacts/show.html.erb @@ -0,0 +1,25 @@ + + +
+
+ <%= 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 new file mode 100644 index 000000000..c9bc80150 --- /dev/null +++ b/app/views/registrant/contacts/show/_address.html.erb @@ -0,0 +1,31 @@ +
+
+

+ <%= 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 new file mode 100644 index 000000000..83b7f49d5 --- /dev/null +++ b/app/views/registrant/contacts/show/_domain.html.erb @@ -0,0 +1,6 @@ + + <%= 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 new file mode 100644 index 000000000..1bd282987 --- /dev/null +++ b/app/views/registrant/contacts/show/_domains.html.erb @@ -0,0 +1,54 @@ +<% domains = contact.all_domains(page: params[:domain_page], per: 20, params: + params.merge(leave_domains: domain_ids)) %> + +
+
+
+
+ <%= 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 %> +
+
+ + +
\ No newline at end of file diff --git a/app/views/registrant/contacts/show/_general.html.erb b/app/views/registrant/contacts/show/_general.html.erb new file mode 100644 index 000000000..b61d2f50e --- /dev/null +++ b/app/views/registrant/contacts/show/_general.html.erb @@ -0,0 +1,48 @@ +
+
+

+ <%= 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 new file mode 100644 index 000000000..f44fa322f --- /dev/null +++ b/app/views/registrant/contacts/show/_search.html.erb @@ -0,0 +1,6 @@ +<%= 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 new file mode 100644 index 000000000..07db6bc87 --- /dev/null +++ b/app/views/registrant/contacts/show/_statuses.html.erb @@ -0,0 +1,25 @@ +
+
+ <%= 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/registrar/contacts/partials/_general.haml b/app/views/registrar/contacts/partials/_general.haml index 462bf35a0..5fc8ec027 100644 --- a/app/views/registrar/contacts/partials/_general.haml +++ b/app/views/registrar/contacts/partials/_general.haml @@ -6,9 +6,10 @@ %dt= t(:id) %dd= @contact.id - %dt= t(:authinfo_pw) + %dt= Contact.human_attribute_name :auth_info %dd - = text_field_tag :password, @contact.password, readonly: true, class: 'partially-hidden' + = tag :input, type: 'text', value: @contact.password, readonly: true, + class: 'form-control input-sm' %br diff --git a/bin/rails b/bin/rails index 284b01d72..5191e6927 100755 --- a/bin/rails +++ b/bin/rails @@ -1,9 +1,4 @@ #!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError - 'no spring' -end -APP_PATH = File.expand_path('../../config/application', __FILE__) +APP_PATH = File.expand_path('../../config/application', __FILE__) require_relative '../config/boot' require 'rails/commands' diff --git a/bin/rake b/bin/rake index 7b36ecbff..17240489f 100755 --- a/bin/rake +++ b/bin/rake @@ -1,9 +1,4 @@ #!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError - 'no spring' -end require_relative '../config/boot' require 'rake' Rake.application.run diff --git a/bin/rspec b/bin/rspec index 534d2bb5f..8bc84617e 100755 --- a/bin/rspec +++ b/bin/rspec @@ -1,8 +1,4 @@ #!/usr/bin/env ruby -begin - load File.expand_path("../spring", __FILE__) -rescue LoadError -end # # This file was generated by Bundler. # diff --git a/bin/setup b/bin/setup new file mode 100644 index 000000000..acdb2c138 --- /dev/null +++ b/bin/setup @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +Dir.chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file: + + puts "== Installing dependencies ==" + system "gem install bundler --conservative" + system "bundle check || bundle install" + + # puts "\n== Copying sample files ==" + # unless File.exist?("config/database.yml") + # system "cp config/database.yml.sample config/database.yml" + # end + + puts "\n== Preparing database ==" + system "bin/rake db:setup" + + puts "\n== Removing old logs and tempfiles ==" + system "rm -f log/*" + system "rm -rf tmp/cache" + + puts "\n== Restarting application server ==" + system "touch tmp/restart.txt" +end diff --git a/bin/spring b/bin/spring deleted file mode 100755 index 7b45d374f..000000000 --- a/bin/spring +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env ruby - -# This file loads spring without using Bundler, in order to be fast. -# It gets overwritten when you run the `spring binstub` command. - -unless defined?(Spring) - require "rubygems" - require "bundler" - - if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m) - Gem.paths = { "GEM_PATH" => [Bundler.bundle_path.to_s, *Gem.path].uniq } - gem "spring", match[1] - require "spring/binstub" - end -end diff --git a/config/environments/test.rb b/config/environments/test.rb index 3b82ee748..544370369 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -2,7 +2,7 @@ Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. config.cache_classes = true - config.eager_load = true + config.eager_load = false config.serve_static_files = true config.static_cache_control = 'public, max-age=3600' @@ -25,4 +25,4 @@ Rails.application.configure do config.cache_store = :memory_store end -Que.mode = :sync \ No newline at end of file +Que.mode = :sync diff --git a/config/locales/registrant/contacts.en.yml b/config/locales/registrant/contacts.en.yml new file mode 100644 index 000000000..ef6ea173f --- /dev/null +++ b/config/locales/registrant/contacts.en.yml @@ -0,0 +1,18 @@ +en: + registrant: + contacts: + show: + general: + header: General + + address: + header: Address + + statuses: + header: Statuses + status: Status + notes: Note + + domains: + header: Domains + all: All roles \ No newline at end of file diff --git a/config/locales/registrar/nameservers.en.yml b/config/locales/registrar/nameservers.en.yml index fbe4c387e..6cc08f0ab 100644 --- a/config/locales/registrar/nameservers.en.yml +++ b/config/locales/registrar/nameservers.en.yml @@ -3,3 +3,4 @@ en: nameservers: update: replaced: Nameserver have been successfully replaced + affected_domains: Affected domains diff --git a/config/routes.rb b/config/routes.rb index 6c78b1742..ba7804de3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -108,6 +108,8 @@ Rails.application.routes.draw do post 'id' => 'sessions#id' end + resources :registrars, only: :show + resources :contacts, only: :show resources :domains, only: %i[index show] do collection do get :download_list @@ -118,30 +120,22 @@ Rails.application.routes.draw do end end - resources :domain_update_confirms - resources :domain_delete_confirms - resources :domains do - resources :registrant_verifications - collection do - post 'update', as: 'update' - post 'destroy', as: 'destroy' - get 'renew' - get 'edit' - get 'info' - get 'delete' - end - end + resources :domain_update_confirms, only: %i[show update] + resources :domain_delete_confirms, only: %i[show update] - resources :registrars do - collection do - get :search - end - end + devise_scope :user do + get 'login' => 'sessions#login' + get 'login/mid' => 'sessions#login_mid' + post 'login/mid' => 'sessions#mid' + post 'login/mid_status' => 'sessions#mid_status' - resources :contacts + post 'sessions' => 'sessions#create' + post 'mid' => 'sessions#mid' + post 'id' => 'sessions#id' + get 'logout' => '/devise/sessions#destroy' + end end - # ADMIN ROUTES namespace :admin do root 'dashboard#show' diff --git a/config/spring.rb b/config/spring.rb deleted file mode 100644 index 12c701147..000000000 --- a/config/spring.rb +++ /dev/null @@ -1 +0,0 @@ -Spring.watch 'config/application.yml' diff --git a/db/migrate/20180612042234_enable_pgcrypto_ext.rb b/db/migrate/20180612042234_enable_pgcrypto_ext.rb new file mode 100644 index 000000000..4e8df65bf --- /dev/null +++ b/db/migrate/20180612042234_enable_pgcrypto_ext.rb @@ -0,0 +1,5 @@ +class EnablePgcryptoExt < ActiveRecord::Migration + def change + enable_extension 'pgcrypto' + end +end diff --git a/db/migrate/20180612042625_add_uuid_to_contacts.rb b/db/migrate/20180612042625_add_uuid_to_contacts.rb new file mode 100644 index 000000000..c80d60e71 --- /dev/null +++ b/db/migrate/20180612042625_add_uuid_to_contacts.rb @@ -0,0 +1,5 @@ +class AddUuidToContacts < ActiveRecord::Migration + def change + add_column :contacts, :uuid, :uuid, default: 'gen_random_uuid()' + end +end diff --git a/db/migrate/20180612042953_add_uuid_to_domains.rb b/db/migrate/20180612042953_add_uuid_to_domains.rb new file mode 100644 index 000000000..6ca609de3 --- /dev/null +++ b/db/migrate/20180612042953_add_uuid_to_domains.rb @@ -0,0 +1,5 @@ +class AddUuidToDomains < ActiveRecord::Migration + def change + add_column :domains, :uuid, :uuid, default: 'gen_random_uuid()' + end +end diff --git a/db/migrate/20180613030330_change_contacts_and_domains_uuid_to_not_null.rb b/db/migrate/20180613030330_change_contacts_and_domains_uuid_to_not_null.rb new file mode 100644 index 000000000..9d7641082 --- /dev/null +++ b/db/migrate/20180613030330_change_contacts_and_domains_uuid_to_not_null.rb @@ -0,0 +1,6 @@ +class ChangeContactsAndDomainsUuidToNotNull < ActiveRecord::Migration + def change + change_column_null :contacts, :uuid, false + change_column_null :domains, :uuid, false + end +end diff --git a/db/migrate/20180613045614_add_contacts_and_domains_uuid_uniq_constraint.rb b/db/migrate/20180613045614_add_contacts_and_domains_uuid_uniq_constraint.rb new file mode 100644 index 000000000..32b8fb090 --- /dev/null +++ b/db/migrate/20180613045614_add_contacts_and_domains_uuid_uniq_constraint.rb @@ -0,0 +1,16 @@ +# Unique constraint is needed to prevent accidental duplicate values in fixtures to appear in DB +class AddContactsAndDomainsUuidUniqConstraint < ActiveRecord::Migration + def up + execute <<-SQL + ALTER TABLE contacts ADD CONSTRAINT uniq_contact_uuid UNIQUE (uuid); + ALTER TABLE domains ADD CONSTRAINT uniq_domain_uuid UNIQUE (uuid); + SQL + end + + def down + execute <<-SQL + ALTER TABLE contacts DROP CONSTRAINT uniq_contact_uuid; + ALTER TABLE domains DROP CONSTRAINT uniq_domain_uuid; + SQL + end +end diff --git a/db/structure.sql b/db/structure.sql index 744ea9e19..b491b6f5a 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -51,6 +51,20 @@ CREATE EXTENSION IF NOT EXISTS hstore WITH SCHEMA public; COMMENT ON EXTENSION hstore IS 'data type for storing sets of (key, value) pairs'; +-- +-- Name: pgcrypto; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA public; + + +-- +-- Name: EXTENSION pgcrypto; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION pgcrypto IS 'cryptographic functions'; + + SET search_path = public, pg_catalog; -- @@ -625,7 +639,8 @@ CREATE TABLE contacts ( original_id integer, ident_updated_at timestamp without time zone, upid integer, - up_date timestamp without time zone + up_date timestamp without time zone, + uuid uuid DEFAULT gen_random_uuid() NOT NULL ); @@ -897,7 +912,8 @@ CREATE TABLE domains ( status_notes hstore, statuses_backup character varying[] DEFAULT '{}'::character varying[], upid integer, - up_date timestamp without time zone + up_date timestamp without time zone, + uuid uuid DEFAULT gen_random_uuid() NOT NULL ); @@ -3242,6 +3258,22 @@ ALTER TABLE ONLY settings ADD CONSTRAINT settings_pkey PRIMARY KEY (id); +-- +-- Name: uniq_contact_uuid; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY contacts + ADD CONSTRAINT uniq_contact_uuid UNIQUE (uuid); + + +-- +-- Name: uniq_domain_uuid; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY domains + ADD CONSTRAINT uniq_domain_uuid UNIQUE (uuid); + + -- -- Name: unique_code; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- @@ -4716,3 +4748,13 @@ INSERT INTO schema_migrations (version) VALUES ('20180327151906'); INSERT INTO schema_migrations (version) VALUES ('20180331200125'); +INSERT INTO schema_migrations (version) VALUES ('20180612042234'); + +INSERT INTO schema_migrations (version) VALUES ('20180612042625'); + +INSERT INTO schema_migrations (version) VALUES ('20180612042953'); + +INSERT INTO schema_migrations (version) VALUES ('20180613030330'); + +INSERT INTO schema_migrations (version) VALUES ('20180613045614'); + diff --git a/doc/repp/v1/nameservers.md b/doc/repp/v1/nameservers.md index 702a0c186..8190530d7 100644 --- a/doc/repp/v1/nameservers.md +++ b/doc/repp/v1/nameservers.md @@ -34,8 +34,9 @@ Content-Type: application/json "hostname": "new-ns1.example.com", "ipv4": ["192.0.2.1", "192.0.2.2"], "ipv6": ["2001:db8::1", "2001:db8::2"] - }, - } + } + }, + "affected_domains": ["example.com", "example.org"] } ``` diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 5c5f523de..000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,33 +0,0 @@ -version: "3.2" - -services: - app: - tty: true - stdin_open: true - build: - context: . - dockerfile: Dockerfile - links: - - db - environment: - - APP_DBHOST=db - volumes: - - .:/opt/webapps/app - ports: - - "3000:3000" - command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails server -p 3000 -b '0.0.0.0'" - - web: - image: nginx - volumes: - - ./docker/nginx.template:/etc/nginx/conf.d/nginx.template - ports: - - "80:80" - links: - - app - environment: - APP: 'app' - command: /bin/bash -c "envsubst '$$APP' < /etc/nginx/conf.d/nginx.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" - - db: - image: postgres:9.4 diff --git a/docker/docker_dev.sh b/docker/docker_dev.sh deleted file mode 100755 index f5592517f..000000000 --- a/docker/docker_dev.sh +++ /dev/null @@ -1,6 +0,0 @@ -# /bin/sh -docker-compose down -docker-compose build -docker-compose run app rake db:setup:all -docker-compose run app rake db:migrate -docker-compose run app rake dev:prime diff --git a/docker/docker_test.sh b/docker/docker_test.sh deleted file mode 100755 index 7239f78a9..000000000 --- a/docker/docker_test.sh +++ /dev/null @@ -1,8 +0,0 @@ -# /bin/sh -docker-compose down -docker-compose build - -# Setup test database -docker-compose run app rake db:setup:all test -# Finally run tests to check if everything is in order -docker-compose run app rspec diff --git a/docker/nginx.template b/docker/nginx.template deleted file mode 100644 index 50f6e8548..000000000 --- a/docker/nginx.template +++ /dev/null @@ -1,29 +0,0 @@ -log_format le_json '{ "time": "$time_iso8601", ' - '"remote_addr": "$remote_addr", ' - '"remote_user": "$remote_user", ' - '"body_bytes_sent": "$body_bytes_sent", ' - '"request_time": "$request_time", ' - '"status": "$status", ' - '"request": "$request", ' - '"request_method": "$request_method", ' - '"http_referrer": "$http_referer", ' - '"http_user_agent": "$http_user_agent" }'; - -upstream app { - server ${APP}:3000; -} - -server { - listen 80; - - access_log /var/log/nginx/access.log le_json; - - location / { - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $http_host; - proxy_redirect off; - proxy_pass http://app; - break; - } -} diff --git a/lib/action_controller/api.rb b/lib/action_controller/api.rb new file mode 100644 index 000000000..5a9fd4512 --- /dev/null +++ b/lib/action_controller/api.rb @@ -0,0 +1,149 @@ +# frozen_string_literal: true + +require "action_view" +require "action_controller" +require "action_controller/log_subscriber" + +module ActionController + # API Controller is a lightweight version of ActionController::Base, + # created for applications that don't require all functionalities that a complete + # \Rails controller provides, allowing you to create controllers with just the + # features that you need for API only applications. + # + # An API Controller is different from a normal controller in the sense that + # by default it doesn't include a number of features that are usually required + # by browser access only: layouts and templates rendering, cookies, sessions, + # flash, assets, and so on. This makes the entire controller stack thinner, + # suitable for API applications. It doesn't mean you won't have such + # features if you need them: they're all available for you to include in + # your application, they're just not part of the default API controller stack. + # + # Normally, +ApplicationController+ is the only controller that inherits from + # ActionController::API. All other controllers in turn inherit from + # +ApplicationController+. + # + # A sample controller could look like this: + # + # class PostsController < ApplicationController + # def index + # posts = Post.all + # render json: posts + # end + # end + # + # Request, response, and parameters objects all work the exact same way as + # ActionController::Base. + # + # == Renders + # + # The default API Controller stack includes all renderers, which means you + # can use render :json and brothers freely in your controllers. Keep + # in mind that templates are not going to be rendered, so you need to ensure + # your controller is calling either render or redirect_to in + # all actions, otherwise it will return 204 No Content. + # + # def show + # post = Post.find(params[:id]) + # render json: post + # end + # + # == Redirects + # + # Redirects are used to move from one action to another. You can use the + # redirect_to method in your controllers in the same way as in + # ActionController::Base. For example: + # + # def create + # redirect_to root_url and return if not_authorized? + # # do stuff here + # end + # + # == Adding New Behavior + # + # In some scenarios you may want to add back some functionality provided by + # ActionController::Base that is not present by default in + # ActionController::API, for instance MimeResponds. This + # module gives you the respond_to method. Adding it is quite simple, + # you just need to include the module in a specific controller or in + # +ApplicationController+ in case you want it available in your entire + # application: + # + # class ApplicationController < ActionController::API + # include ActionController::MimeResponds + # end + # + # class PostsController < ApplicationController + # def index + # posts = Post.all + # + # respond_to do |format| + # format.json { render json: posts } + # format.xml { render xml: posts } + # end + # end + # end + # + # Make sure to check the modules included in ActionController::Base + # if you want to use any other functionality that is not provided + # by ActionController::API out of the box. + class API < Metal + abstract! + + # Shortcut helper that returns all the ActionController::API modules except + # the ones passed as arguments: + # + # class MyAPIBaseController < ActionController::Metal + # ActionController::API.without_modules(:ForceSSL, :UrlFor).each do |left| + # include left + # end + # end + # + # This gives better control over what you want to exclude and makes it easier + # to create an API controller class, instead of listing the modules required + # manually. + def self.without_modules(*modules) + modules = modules.map do |m| + m.is_a?(Symbol) ? ActionController.const_get(m) : m + end + + MODULES - modules + end + + MODULES = [ + AbstractController::Rendering, + + UrlFor, + Redirecting, + ApiRendering, + Renderers::All, + ConditionalGet, + BasicImplicitRender, + StrongParameters, + + ForceSSL, + DataStreaming, + + # Before callbacks should also be executed as early as possible, so + # also include them at the bottom. + AbstractController::Callbacks, + + # Append rescue at the bottom to wrap as much as possible. + Rescue, + + # Add instrumentations hooks at the bottom, to ensure they instrument + # all the methods properly. + Instrumentation, + + # Params wrapper should come before instrumentation so they are + # properly showed in logs + ParamsWrapper + ] + + MODULES.each do |mod| + include mod + end + + ActiveSupport.run_load_hooks(:action_controller_api, self) + ActiveSupport.run_load_hooks(:action_controller, self) + end +end diff --git a/lib/action_controller/api/api_rendering.rb b/lib/action_controller/api/api_rendering.rb new file mode 100644 index 000000000..52e9f60fc --- /dev/null +++ b/lib/action_controller/api/api_rendering.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module ActionController + module ApiRendering + extend ActiveSupport::Concern + + included do + include Rendering + end + + def render_to_body(options = {}) + _process_options(options) + super + end + end +end \ No newline at end of file diff --git a/lib/action_controller/metal/basic_implicit_render.rb b/lib/action_controller/metal/basic_implicit_render.rb new file mode 100644 index 000000000..9030ea585 --- /dev/null +++ b/lib/action_controller/metal/basic_implicit_render.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module ActionController + module BasicImplicitRender # :nodoc: + def send_action(method, *args) + super.tap { default_render unless performed? } + end + + def default_render(*args) + head :no_content + end + end +end \ No newline at end of file diff --git a/lib/gem_ext/paper_trail.rb b/lib/gem_ext/paper_trail.rb index 200e71d48..c8454e550 100644 --- a/lib/gem_ext/paper_trail.rb +++ b/lib/gem_ext/paper_trail.rb @@ -6,7 +6,7 @@ PaperTrail::Version.module_eval do end # Store console and rake changes in versions -if defined?(::Rails::Console) || File.basename($PROGRAM_NAME).split(' ').first == 'spring' +if defined?(::Rails::Console) PaperTrail.whodunnit = "console-#{`whoami`.strip}" elsif File.basename($PROGRAM_NAME) == 'rake' # rake username does not work when spring enabled diff --git a/lib/rails5_api_controller_backport.rb b/lib/rails5_api_controller_backport.rb new file mode 100644 index 000000000..252332488 --- /dev/null +++ b/lib/rails5_api_controller_backport.rb @@ -0,0 +1,3 @@ +require_relative 'action_controller/metal/basic_implicit_render' +require_relative 'action_controller/api/api_rendering' +require_relative 'action_controller/api' \ No newline at end of file diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake deleted file mode 100644 index 163e3ad1f..000000000 --- a/lib/tasks/dev.rake +++ /dev/null @@ -1,181 +0,0 @@ -namespace :dev do - desc 'Generates dummy data in development environment' \ - ' (options: [random] for random data generation - slowest)' - - task :prime, [:random] => :environment do |t, args| - abort 'Production environment is not supported' if Rails.env.production? - - include FactoryBot::Syntax::Methods - - PaperTrail.enabled = false - Domain.paper_trail_on! - Contact.paper_trail_on! - - with_random_data = args[:random].present? - - def create_domain(name:, registrar:, registrant:, account:, price:, reg_time:) - duration = price.duration.sub('mons', 'months').split("\s") - period = duration.first.to_i - period_unit = duration.second[0] - - create(:domain, - name: name, - period: period, - period_unit: period_unit, - registered_at: reg_time, - expire_time: reg_time + period.send(duration.second.to_sym), - created_at: reg_time, - updated_at: reg_time, - registrar: registrar, - registrant: registrant) - - create(:account_activity, - account: account, - sum: -price.price.amount, - activity_type: AccountActivity::CREATE, - created_at: reg_time, - updated_at: reg_time, - price: price) - end - - def generate_default_data - create(:admin_user, username: 'test', password: 'testtest', password_confirmation: 'testtest') - - zone = create(:zone, origin: 'test') - registrar = create(:registrar, name: 'test') - registrant = create(:registrant, name: 'test', registrar: registrar) - - account = create(:account, registrar: registrar, balance: 1_000_000) - api_user = create(:api_user, username: 'test', password: 'testtest', registrar: registrar) - - epp_session = EppSession.new - epp_session.session_id = 'test' - epp_session.user = api_user - epp_session.save! - - domain_counter = 1.step - - Billing::Price.durations.each do |duration| - Billing::Price.operation_categories.each do |operation_category| - price = create(:price, - price: Money.from_amount(duration.to_i * 10), - valid_from: Time.zone.now - rand(1).months, - valid_to: Time.zone.now + rand(1).months, - duration: duration, - operation_category: operation_category, - zone: zone) - - next if operation_category == 'renew' - - (rand(3) + 1).times do - create_domain(name: "test#{domain_counter.next}.test", - registrar: registrar, - registrant: registrant, - account: account, - price: price, - reg_time: 1.month.ago) - end - - (rand(3) + 1).times do - create_domain(name: "test#{domain_counter.next}.test", - registrar: registrar, - registrant: registrant, - account: account, - price: price, - reg_time: Time.zone.now) - end - end - end - - create_domain(name: 'test.test', - registrar: registrar, - registrant: registrant, - account: account, - price: Billing::Price.first, - reg_time: Time.zone.now) - end - - def generate_random_data - zone_count = 10 - admin_user_count = 5 - registrar_count = 50 - api_user_count = 10 - registrant_count = 50 - domain_count = 50 - registrars = [] - registrants = [] - zones = [] - registrant_names = [ - 'John Doe', - 'John Roe', - 'Jane Doe', - 'Jane Roe', - 'John Smith', - ] - - zone_count.times do - origin = SecureRandom.hex[0..(rand(5) + 1)] - zones << create(:zone, origin: origin) - end - - zone_origins = zones.collect { |zone| zone.origin } - - admin_user_count.times do - uid = SecureRandom.hex[0..(rand(5) + 1)] - create(:admin_user, username: "test#{uid}", password: 'testtest', password_confirmation: 'testtest') - end - - registrar_count.times do - uid = SecureRandom.hex[0..(rand(5) + 1)] - registrars << create(:registrar, name: "Acme Ltd. #{uid}") - end - - registrars.each do |registrar| - create(:account, registrar: registrar, balance: rand(99999)) - - api_user_count.times do |i| - create(:api_user, username: "test#{registrar.id}#{i}", password: 'testtest', registrar: registrar) - end - - registrant_count.times do |i| - registrants << create(:registrant, name: registrant_names.sample, registrar: registrar) - end - - domain_count.times do |i| - name = "test#{registrar.id}#{i}#{rand(99999)}.#{zone_origins.sample}" - period = rand(3) + 1 - - create(:domain, - name: name, - period: period, - period_unit: 'y', - registered_at: Time.zone.now, - expire_time: Time.zone.now + period.years, - registrar: registrar, - registrant: registrants.sample) - end - end - - zones.each do |zone| - Billing::Price.durations.each do |duration| - Billing::Price.operation_categories.each do |operation_category| - create(:price, - price: Money.from_amount(rand(10) + 1), - valid_from: Time.zone.now.beginning_of_day, - valid_to: Time.zone.now + (rand(10) + 1).years, - duration: duration, - operation_category: operation_category, - zone: zone) - end - end - end - end - - Setting.address_processing = false - - ActiveRecord::Base.transaction do - generate_default_data - generate_random_data if with_random_data - end - end -end diff --git a/spec/jobs/domain_delete_confirm_email_job_spec.rb b/spec/jobs/domain_delete_confirm_email_job_spec.rb deleted file mode 100644 index 0b2a0a6b7..000000000 --- a/spec/jobs/domain_delete_confirm_email_job_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'rails_helper' - -RSpec.describe DomainDeleteConfirmEmailJob do - describe '#run' do - let(:domain) { instance_double(Domain) } - let(:message) { instance_double(ActionMailer::MessageDelivery) } - - before :example do - expect(Domain).to receive(:find).and_return(domain) - allow(domain).to receive_messages( - id: 1, - name: 'test.com', - registrant_email: 'registrant@test.com', - registrar: 'registrar', - registrant: 'registrant') - end - - after :example do - domain_id = 1 - described_class.enqueue(domain_id) - end - - it 'creates log record' do - log_message = 'Send DomainDeleteMailer#confirm email for domain test.com (#1) to registrant@test.com' - - allow(DomainDeleteMailer).to receive(:confirm).and_return(message) - allow(message).to receive(:deliver_now) - - expect(Rails.logger).to receive(:info).with(log_message) - end - - it 'sends email' do - expect(DomainDeleteMailer).to receive(:confirm).with(domain: domain, - registrar: 'registrar', - registrant: 'registrant') - .and_return(message) - expect(message).to receive(:deliver_now) - end - end -end diff --git a/spec/jobs/domain_update_confirm_job_spec.rb b/spec/jobs/domain_update_confirm_job_spec.rb deleted file mode 100644 index 4748ca021..000000000 --- a/spec/jobs/domain_update_confirm_job_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'rails_helper' - -RSpec.describe DomainUpdateConfirmJob do - let(:domain) { instance_spy(Epp::Domain, registrant: registrant, errors: []) } - let(:registrant) { instance_double(Registrant) } - let(:registrant_change) { instance_spy(RegistrantChange) } - - it 'confirms registrant change' do - expect(Epp::Domain).to receive(:find).and_return(domain) - expect(RegistrantChange).to receive(:new) - .with(domain: domain, old_registrant: registrant) - .and_return(registrant_change) - - described_class.enqueue(domain_id = nil, action = RegistrantVerification::CONFIRMED) - - expect(registrant_change).to have_received(:confirm) - end -end diff --git a/test/fixtures/contacts.yml b/test/fixtures/contacts.yml index b64dce039..1f2e4b8da 100644 --- a/test/fixtures/contacts.yml +++ b/test/fixtures/contacts.yml @@ -8,6 +8,7 @@ john: registrar: bestnames code: john-001 auth_info: cacb5b + uuid: eb2f2766-b44c-4e14-9f16-32ab1a7cb957 william: &william name: William @@ -27,6 +28,7 @@ william: &william country_code: US statuses: - ok + uuid: 0aa54704-d6f7-4ca9-b8ca-2827d9a4e4eb jane: name: Jane @@ -38,6 +40,7 @@ jane: registrar: bestnames code: jane-001 auth_info: 0aa09f + uuid: 9db3de62-2414-4487-bee2-d5c155567768 acme_ltd: name: Acme Ltd @@ -49,6 +52,7 @@ acme_ltd: ident_country_code: US code: acme-ltd-001 auth_info: 720b3c + uuid: f1dd365c-5be9-4b3d-a44e-3fa002465e4d jack: name: Jack @@ -60,12 +64,14 @@ jack: ident_country_code: US code: jack-001 auth_info: e2c440 + uuid: 28b65455-6f1a-49fd-961c-0758886dbd75 identical_to_william: <<: *william registrar: goodnames code: william-002 auth_info: 5ab865 + uuid: c0a191d5-3793-4f0b-8f85-491612d0293e not_in_use: name: Useless @@ -73,6 +79,7 @@ not_in_use: registrar: bestnames code: useless-001 auth_info: e75a2a + uuid: ca613cc5-a8dc-48c1-8d32-d3c6a0b6c952 invalid: name: any @@ -80,3 +87,4 @@ invalid: email: invalid@invalid.test auth_info: any registrar: bestnames + uuid: bd80c0f9-26ee-49e0-a2cb-2311d931c433 \ No newline at end of file diff --git a/test/fixtures/domains.yml b/test/fixtures/domains.yml index 53de2837b..59a1b8ea5 100644 --- a/test/fixtures/domains.yml +++ b/test/fixtures/domains.yml @@ -7,6 +7,7 @@ shop: valid_to: 2010-07-05 period: 1 period_unit: m + uuid: 1b3ee442-e8fe-4922-9492-8fcb9dccc69c airport: name: airport.test @@ -17,6 +18,7 @@ airport: valid_to: 2010-07-05 period: 1 period_unit: m + uuid: 2df2c1a1-8f6a-490a-81be-8bdf29866880 library: name: library.test @@ -27,6 +29,7 @@ library: valid_to: 2010-07-05 period: 1 period_unit: m + uuid: 647bcc48-8d5e-4a04-8ce5-2a3cd17b6eab metro: name: metro.test @@ -37,6 +40,7 @@ metro: valid_to: 2010-07-05 period: 1 period_unit: m + uuid: ef97cb80-333b-4893-b9df-163f2b452798 invalid: name: invalid.test @@ -44,3 +48,4 @@ invalid: valid_to: <%= Time.zone.parse('2010-07-05').utc.to_s(:db) %> registrar: bestnames registrant: invalid + uuid: 3c430ead-bb17-4b5b-aaa1-caa7dde7e138 \ No newline at end of file diff --git a/test/fixtures/invoices.yml b/test/fixtures/invoices.yml index 71189f6b6..6b9359343 100644 --- a/test/fixtures/invoices.yml +++ b/test/fixtures/invoices.yml @@ -35,5 +35,4 @@ overdue: for_payments_test: <<: *DEFAULTS total: 12.00 - id: 1 number: 1 diff --git a/test/fixtures/whois_records.yml b/test/fixtures/whois_records.yml new file mode 100644 index 000000000..0cdd25431 --- /dev/null +++ b/test/fixtures/whois_records.yml @@ -0,0 +1,6 @@ +shop: + name: shop.test + domain: shop + body: WHOIS text + json: + name: shop.test diff --git a/test/integration/api/nameservers/put_test.rb b/test/integration/api/nameservers/put_test.rb index 416510541..0967a1169 100644 --- a/test/integration/api/nameservers/put_test.rb +++ b/test/integration/api/nameservers/put_test.rb @@ -41,11 +41,12 @@ class APINameserversPutTest < ActionDispatch::IntegrationTest assert_equal nameserver_hash, nameservers(:metro_ns1).reload.attributes end - def test_returns_new_nameserver_record + def test_returns_new_nameserver_record_and_affected_domain request_params = { format: :json, data: { type: 'nameserver', id: 'ns1.bestnames.test', attributes: { hostname: 'ns55.bestnames.test', ipv4: ['192.0.2.55'], ipv6: ['2001:db8::55'] } } } + put '/repp/v1/registrar/nameservers', request_params, { 'HTTP_AUTHORIZATION' => http_auth_key } assert_response 200 @@ -53,7 +54,8 @@ class APINameserversPutTest < ActionDispatch::IntegrationTest id: 'ns55.bestnames.test', attributes: { hostname: 'ns55.bestnames.test', ipv4: ['192.0.2.55'], - ipv6: ['2001:db8::55'] } } }), + ipv6: ['2001:db8::55'] }}, + affected_domains: ["airport.test", "shop.test"] }), JSON.parse(response.body, symbolize_names: true) end diff --git a/test/integration/registrar/bulk_change/nameserver_test.rb b/test/integration/registrar/bulk_change/nameserver_test.rb index 20fd6617d..841e68db5 100644 --- a/test/integration/registrar/bulk_change/nameserver_test.rb +++ b/test/integration/registrar/bulk_change/nameserver_test.rb @@ -16,8 +16,8 @@ class RegistrarAreaNameserverBulkChangeTest < ActionDispatch::IntegrationTest basic_auth: ['test_goodnames', 'testtest']) .to_return(body: { data: [{ type: 'nameserver', - id: 'new-ns.bestnames.test' - }] }.to_json, status: 200) + id: 'new-ns.bestnames.test'}], + affected_domains: ["airport.test", "shop.test"]}.to_json, status: 200) visit registrar_domains_url click_link 'Bulk change' @@ -32,6 +32,7 @@ class RegistrarAreaNameserverBulkChangeTest < ActionDispatch::IntegrationTest assert_requested request_stub assert_current_path registrar_domains_path assert_text 'Nameserver have been successfully replaced' + assert_text 'Affected domains: airport.test, shop.test' end def test_fails_gracefully diff --git a/test/jobs/domain_delete_confirm_job_test.rb b/test/jobs/domain_delete_confirm_job_test.rb new file mode 100644 index 000000000..9127ca628 --- /dev/null +++ b/test/jobs/domain_delete_confirm_job_test.rb @@ -0,0 +1,36 @@ +require "test_helper" + +class DomainDeleteConfirmJobTest < ActiveSupport::TestCase + def setup + super + + @domain = domains(:shop) + @new_registrant = contacts(:william) + @user = users(:api_bestnames) + + @domain.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 }) + end + + def teardown + super + end + + def test_rejected_registrant_verification_polls_a_message + DomainDeleteConfirmJob.enqueue(@domain.id, RegistrantVerification::REJECTED) + + last_registrar_message = @domain.registrar.messages.last + assert_equal(last_registrar_message.attached_obj_id, @domain.id) + assert_equal(last_registrar_message.body, 'Registrant rejected domain deletion: shop.test') + end + + def test_accepted_registrant_verification_polls_a_message + DomainDeleteConfirmJob.enqueue(@domain.id, RegistrantVerification::CONFIRMED) + + last_registrar_message = @domain.registrar.messages.last + assert_equal(last_registrar_message.attached_obj_id, @domain.id) + assert_equal(last_registrar_message.body, 'Registrant confirmed domain deletion: shop.test') + end +end diff --git a/test/jobs/domain_update_confirm_job_test.rb b/test/jobs/domain_update_confirm_job_test.rb new file mode 100644 index 000000000..c507e2c98 --- /dev/null +++ b/test/jobs/domain_update_confirm_job_test.rb @@ -0,0 +1,36 @@ +require "test_helper" + +class DomainUpdateConfirmJobTest < ActiveSupport::TestCase + def setup + super + + @domain = domains(:shop) + @new_registrant = contacts(:william) + @user = users(:api_bestnames) + + @domain.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 }) + end + + def teardown + super + end + + def test_rejected_registrant_verification_polls_a_message + DomainUpdateConfirmJob.enqueue(@domain.id, RegistrantVerification::REJECTED) + + last_registrar_message = @domain.registrar.messages.last + assert_equal(last_registrar_message.attached_obj_id, @domain.id) + assert_equal(last_registrar_message.body, 'Registrant rejected domain update: shop.test') + end + + def test_accepted_registrant_verification_polls_a_message + DomainUpdateConfirmJob.enqueue(@domain.id, RegistrantVerification::CONFIRMED) + + last_registrar_message = @domain.registrar.messages.last + assert_equal(last_registrar_message.attached_obj_id, @domain.id) + assert_equal(last_registrar_message.body, 'Registrant confirmed domain update: shop.test') + end +end diff --git a/test/models/registrar/replace_nameservers_test.rb b/test/models/registrar/replace_nameservers_test.rb new file mode 100644 index 000000000..5bcbb83d1 --- /dev/null +++ b/test/models/registrar/replace_nameservers_test.rb @@ -0,0 +1,23 @@ +require 'test_helper' + +class ReplaceNameserversTest < ActiveSupport::TestCase + def setup + @registrar = registrars(:bestnames) + end + + def test_replace_nameservers_in_bulk_returns_sorted_domain_names + new_attributes = { hostname: 'ns-updated1.bestnames.test', ipv4: '192.0.3.1', + ipv6: '2001:db8::2' } + result = @registrar.replace_nameservers('ns1.bestnames.test', new_attributes) + + assert_equal(["airport.test", "shop.test"], result) + end + + def test_replace_nameservers_in_bulk_returns_empty_array_for_non_existent_base_nameserver + new_attributes = { hostname: 'ns-updated1.bestnames.test', ipv4: '192.0.3.1', + ipv6: '2001:db8::2' } + result = @registrar.replace_nameservers('ns3.bestnames.test', new_attributes) + + assert_equal([], result) + end +end