Merge branch 'master' into registry-927

This commit is contained in:
Maciej Szlosarczyk 2018-08-31 14:25:59 +03:00
commit 2636fe2525
No known key found for this signature in database
GPG key ID: 41D62D42D3B0D765
40 changed files with 313 additions and 105 deletions

View file

@ -1 +1 @@
2.3.7 2.4.4

View file

@ -1,4 +1,4 @@
FROM internetee/ruby:2.3 FROM internetee/ruby:2.4
MAINTAINER maciej.szlosarczyk@internet.ee MAINTAINER maciej.szlosarczyk@internet.ee
RUN mkdir -p /opt/webapps/app/tmp/pids RUN mkdir -p /opt/webapps/app/tmp/pids

View file

@ -29,7 +29,7 @@ module Repp
# example: curl -u registrar1:password localhost:3000/repp/v1/domains/1/transfer_info -H "Auth-Code: authinfopw1" # example: curl -u registrar1:password localhost:3000/repp/v1/domains/1/transfer_info -H "Auth-Code: authinfopw1"
get '/:id/transfer_info', requirements: { id: /.*/ } do get '/:id/transfer_info', requirements: { id: /.*/ } do
ident = params[:id] ident = params[:id]
domain = ident =~ /\A[0-9]+\z/ ? Domain.find_by(id: ident) : Domain.find_by_idn(ident) domain = ident.match?(/\A[0-9]+\z/) ? Domain.find_by(id: ident) : Domain.find_by_idn(ident)
error! I18n.t('errors.messages.epp_domain_not_found'), 404 unless domain error! I18n.t('errors.messages.epp_domain_not_found'), 404 unless domain
error! I18n.t('errors.messages.epp_authorization_error'), 401 unless domain.transfer_code.eql? request.headers['Auth-Code'] error! I18n.t('errors.messages.epp_authorization_error'), 401 unless domain.transfer_code.eql? request.headers['Auth-Code']

View file

@ -1,7 +1,7 @@
module Admin module Admin
class DomainsController < BaseController class DomainsController < BaseController
load_and_authorize_resource before_action :set_domain, only: %i[show edit update keep]
before_action :set_domain, only: [:show, :edit, :update, :zonefile] authorize_resource
helper_method :force_delete_templates helper_method :force_delete_templates
def index def index
@ -33,7 +33,8 @@ module Admin
end end
def show def show
@domain.valid? # Validation is needed to warn users
@domain.validate
end end
def edit def edit
@ -60,6 +61,11 @@ module Admin
@versions = @domain.versions @versions = @domain.versions
end end
def keep
@domain.keep
redirect_to edit_admin_domain_url(@domain), notice: t('.kept')
end
private private
def set_domain def set_domain

View file

@ -145,7 +145,9 @@ class EppController < ApplicationController
# VALIDATION # VALIDATION
def latin_only def latin_only
return true if params['frame'].blank? return true if params['frame'].blank?
return true if params['frame'].match(/\A[\p{Latin}\p{Z}\p{P}\p{S}\p{Cc}\p{Cf}\w_\'\+\-\.\(\)\/]*\Z/i) if params['frame'].match?(/\A[\p{Latin}\p{Z}\p{P}\p{S}\p{Cc}\p{Cf}\w_\'\+\-\.\(\)\/]*\Z/i)
return true
end
epp_errors << { epp_errors << {
msg: 'Parameter value policy error. Allowed only Latin characters.', msg: 'Parameter value policy error. Allowed only Latin characters.',

View file

@ -87,14 +87,14 @@ class Certificate < ActiveRecord::Base
-extensions usr_cert -notext -md sha256 \ -extensions usr_cert -notext -md sha256 \
-in #{csr_file.path} -out #{crt_file.path} -key '#{ENV['ca_key_password']}' -batch") -in #{csr_file.path} -out #{crt_file.path} -key '#{ENV['ca_key_password']}' -batch")
if err.match(/Data Base Updated/) if err.match?(/Data Base Updated/)
crt_file.rewind crt_file.rewind
self.crt = crt_file.read self.crt = crt_file.read
self.md5 = OpenSSL::Digest::MD5.new(parsed_crt.to_der).to_s self.md5 = OpenSSL::Digest::MD5.new(parsed_crt.to_der).to_s
save! save!
else else
logger.error('FAILED TO CREATE CLIENT CERTIFICATE') logger.error('FAILED TO CREATE CLIENT CERTIFICATE')
if err.match(/TXT_DB error number 2/) if err.match?(/TXT_DB error number 2/)
errors.add(:base, I18n.t('failed_to_create_crt_csr_already_signed')) errors.add(:base, I18n.t('failed_to_create_crt_csr_already_signed'))
logger.error('CSR ALREADY SIGNED') logger.error('CSR ALREADY SIGNED')
else else

View file

@ -1,16 +1,25 @@
module Concerns::Domain::Deletable module Concerns::Domain::Deletable
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do private
alias_attribute :delete_time, :delete_at
def delete_later
deletion_time = Time.zone.at(rand(deletion_time_span))
DomainDeleteJob.enqueue(id, run_at: deletion_time, priority: 1)
logger.info "Domain #{name} is scheduled to be deleted around #{deletion_time}"
end end
def discard def do_not_delete_later
statuses << DomainStatus::DELETE_CANDIDATE # Que job can be manually deleted in admin area UI
save QueJob.find_by("args->>0 = '#{id}'", job_class: DomainDeleteJob.name)&.destroy
end end
def discarded? def deletion_time_span
statuses.include?(DomainStatus::DELETE_CANDIDATE) range_params = [Time.zone.now.to_i, deletion_deadline.to_i].sort
Range.new(*range_params)
end end
end
def deletion_deadline
delete_at + 24.hours
end
end

View file

@ -0,0 +1,40 @@
module Concerns::Domain::Discardable
extend ActiveSupport::Concern
class_methods do
def discard_domains
domains = where('delete_at < ? AND ? != ALL(coalesce(statuses, array[]::varchar[])) AND' \
' ? != ALL(COALESCE(statuses, array[]::varchar[]))',
Time.zone.now,
DomainStatus::SERVER_DELETE_PROHIBITED,
DomainStatus::DELETE_CANDIDATE)
domains.each do |domain|
domain.discard
yield domain if block_given?
end
end
end
def discard
raise 'Domain is already discarded' if discarded?
statuses << DomainStatus::DELETE_CANDIDATE
transaction do
save(validate: false)
delete_later
end
end
def keep
statuses.delete(DomainStatus::DELETE_CANDIDATE)
transaction do
save(validate: false)
do_not_delete_later
end
end
def discarded?
statuses.include?(DomainStatus::DELETE_CANDIDATE)
end
end

View file

@ -4,6 +4,7 @@ class Domain < ActiveRecord::Base
include Concerns::Domain::Expirable include Concerns::Domain::Expirable
include Concerns::Domain::Activatable include Concerns::Domain::Activatable
include Concerns::Domain::ForceDelete include Concerns::Domain::ForceDelete
include Concerns::Domain::Discardable
include Concerns::Domain::Deletable include Concerns::Domain::Deletable
include Concerns::Domain::Transferable include Concerns::Domain::Transferable
include Concerns::Domain::RegistryLockable include Concerns::Domain::RegistryLockable
@ -250,13 +251,6 @@ class Domain < ActiveRecord::Base
true true
end end
def delete_candidateable?
return false if delete_at > Time.zone.now
return false if statuses.include?(DomainStatus::DELETE_CANDIDATE)
return false if statuses.include?(DomainStatus::SERVER_DELETE_PROHIBITED)
true
end
def renewable? def renewable?
if Setting.days_to_renew_domain_before_expire != 0 if Setting.days_to_renew_domain_before_expire != 0
# if you can renew domain at days_to_renew before domain expiration # if you can renew domain at days_to_renew before domain expiration
@ -614,10 +608,6 @@ class Domain < ActiveRecord::Base
where("#{attribute_alias(:outzone_time)} < ?", Time.zone.now) where("#{attribute_alias(:outzone_time)} < ?", Time.zone.now)
end end
def self.delete_candidates
where("#{attribute_alias(:delete_time)} < ?", Time.zone.now)
end
def self.uses_zone?(zone) def self.uses_zone?(zone)
exists?(["name ILIKE ?", "%.#{zone.origin}"]) exists?(["name ILIKE ?", "%.#{zone.origin}"])
end end

View file

@ -84,22 +84,6 @@ class DomainCron
c = 0 c = 0
domains = Domain.delete_candidates
domains.each do |domain|
next unless domain.delete_candidateable?
domain.statuses << DomainStatus::DELETE_CANDIDATE
# If domain successfully saved, add it to delete schedule
if domain.save(validate: false)
::PaperTrail.whodunnit = "cron - #{__method__}"
DomainDeleteJob.enqueue(domain.id, run_at: rand(((24*60) - (DateTime.now.hour * 60 + DateTime.now.minute))).minutes.from_now)
STDOUT << "#{Time.zone.now.utc} DomainCron.destroy_delete_candidates: job added by deleteCandidate status ##{domain.id} (#{domain.name})\n" unless Rails.env.test?
c += 1
end
end
Domain.where('force_delete_at <= ?', Time.zone.now.end_of_day.utc).each do |x| Domain.where('force_delete_at <= ?', Time.zone.now.end_of_day.utc).each do |x|
DomainDeleteJob.enqueue(x.id, run_at: rand(((24*60) - (DateTime.now.hour * 60 + DateTime.now.minute))).minutes.from_now) DomainDeleteJob.enqueue(x.id, run_at: rand(((24*60) - (DateTime.now.hour * 60 + DateTime.now.minute))).minutes.from_now)
STDOUT << "#{Time.zone.now.utc} DomainCron.destroy_delete_candidates: job added by force delete time ##{x.id} (#{x.name})\n" unless Rails.env.test? STDOUT << "#{Time.zone.now.utc} DomainCron.destroy_delete_candidates: job added by force delete time ##{x.id} (#{x.name})\n" unless Rails.env.test?

View file

@ -153,13 +153,11 @@ class DomainStatus < ActiveRecord::Base
[ [
['Hold', SERVER_HOLD], ['Hold', SERVER_HOLD],
['ManualInzone', SERVER_MANUAL_INZONE], ['ManualInzone', SERVER_MANUAL_INZONE],
# [''],
['RenewProhibited', SERVER_RENEW_PROHIBITED], ['RenewProhibited', SERVER_RENEW_PROHIBITED],
['TransferProhibited', SERVER_TRANSFER_PROHIBITED], ['TransferProhibited', SERVER_TRANSFER_PROHIBITED],
['RegistrantChangeProhibited', SERVER_REGISTRANT_CHANGE_PROHIBITED], ['RegistrantChangeProhibited', SERVER_REGISTRANT_CHANGE_PROHIBITED],
['AdminChangeProhibited', SERVER_ADMIN_CHANGE_PROHIBITED], ['AdminChangeProhibited', SERVER_ADMIN_CHANGE_PROHIBITED],
['TechChangeProhibited', SERVER_TECH_CHANGE_PROHIBITED], ['TechChangeProhibited', SERVER_TECH_CHANGE_PROHIBITED],
# [''],
['UpdateProhibited', SERVER_UPDATE_PROHIBITED], ['UpdateProhibited', SERVER_UPDATE_PROHIBITED],
['DeleteProhibited', SERVER_DELETE_PROHIBITED] ['DeleteProhibited', SERVER_DELETE_PROHIBITED]
] ]
@ -171,11 +169,11 @@ class DomainStatus < ActiveRecord::Base
INACTIVE, INACTIVE,
FORCE_DELETE, FORCE_DELETE,
PENDING_CREATE, PENDING_CREATE,
#PENDING_DELETE,
PENDING_RENEW, PENDING_RENEW,
PENDING_TRANSFER, PENDING_TRANSFER,
PENDING_UPDATE, PENDING_UPDATE,
PENDING_DELETE_CONFIRMATION PENDING_DELETE_CONFIRMATION,
DELETE_CANDIDATE,
] ]
end end
end end

View file

@ -100,18 +100,18 @@ class Nameserver < ActiveRecord::Base
def check_puny_symbols def check_puny_symbols
regexp = /(\A|\.)..--/ regexp = /(\A|\.)..--/
errors.add(:hostname, :invalid) if hostname =~ regexp errors.add(:hostname, :invalid) if hostname.match?(regexp)
end end
def validate_ipv4_format def validate_ipv4_format
ipv4.to_a.each do |ip| ipv4.to_a.each do |ip|
errors.add(:ipv4, :invalid) unless ip =~ IPV4_REGEXP errors.add(:ipv4, :invalid) unless ip.match?(IPV4_REGEXP)
end end
end end
def validate_ipv6_format def validate_ipv6_format
ipv6.to_a.each do |ip| ipv6.to_a.each do |ip|
errors.add(:ipv6, :invalid) unless ip =~ IPV6_REGEXP errors.add(:ipv6, :invalid) unless ip.match?(IPV6_REGEXP)
end end
end end
end end

4
app/models/que_job.rb Normal file
View file

@ -0,0 +1,4 @@
# To be able to remove existing jobs
class QueJob < ActiveRecord::Base
self.primary_key = 'job_id'
end

View file

@ -35,7 +35,7 @@ class DomainPresenter
end end
def delete_date def delete_date
view.l(domain.delete_time, format: :date) if domain.delete_time view.l(domain.delete_at, format: :date) if domain.delete_at
end end
def force_delete_date def force_delete_date
@ -73,6 +73,15 @@ class DomainPresenter
class: 'dropdown-item') class: 'dropdown-item')
end end
def keep_btn
return unless domain.discarded?
view.link_to view.t('admin.domains.edit.keep_btn'), view.keep_admin_domain_path(@domain),
method: :patch,
data: { confirm: view.t('admin.domains.edit.keep_btn_confirm') },
class: 'btn btn-default'
end
private private
def schedule_force_delete_btn def schedule_force_delete_btn

View file

@ -10,7 +10,8 @@ class Contact::Ident::RegNoValidator < ActiveModel::EachValidator
return unless format return unless format
record.errors.add(attribute, :invalid_reg_no, country: record.country) unless value =~ format return if value.match?(format)
record.errors.add(attribute, :invalid_reg_no, country: record.country)
end end
private private

View file

@ -22,7 +22,7 @@ class DomainNameValidator < ActiveModel::EachValidator
# it's punycode # it's punycode
if value[2] == '-' && value[3] == '-' if value[2] == '-' && value[3] == '-'
regexp = /\Axn--[a-zA-Z0-9-]{0,59}\.#{general_domains}\z/ regexp = /\Axn--[a-zA-Z0-9-]{0,59}\.#{general_domains}\z/
return false unless value =~ regexp return false unless value.match?(regexp)
value = SimpleIDN.to_unicode(value).mb_chars.downcase.strip value = SimpleIDN.to_unicode(value).mb_chars.downcase.strip
end end

View file

@ -22,6 +22,7 @@
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><%= domain.force_delete_toggle_btn %></li> <li><%= domain.force_delete_toggle_btn %></li>
<li><%= domain.remove_registry_lock_btn %></li> <li><%= domain.remove_registry_lock_btn %></li>
<li><%= domain.keep_btn %></li>
<div class="divider"></div> <div class="divider"></div>
<li><%= link_to t('.add_new_status_btn'), '#', class: 'js-add-status' %></li> <li><%= link_to t('.add_new_status_btn'), '#', class: 'js-add-status' %></li>
</ul> </ul>

View file

@ -15,6 +15,11 @@ en:
edit: edit:
header: "Edit:" header: "Edit:"
add_new_status_btn: Add new status add_new_status_btn: Add new status
keep_btn: Remove deleteCandidate status
keep_btn_confirm: Are you sure you want to remove deleteCandidate status?
keep:
kept: deleteCandidate status has been removed
force_delete_dialog: force_delete_dialog:
title: Force delete title: Force delete

View file

@ -192,12 +192,16 @@ Rails.application.routes.draw do
match 'forward', via: [:post, :get] match 'forward', via: [:post, :get]
end end
resources :domains do resources :domains, except: %i[new create destroy] do
resources :domain_versions, controller: 'domains', action: 'versions' resources :domain_versions, controller: 'domains', action: 'versions'
resources :pending_updates resources :pending_updates
resources :pending_deletes resources :pending_deletes
resource :force_delete, controller: 'domains/force_delete', only: %i[create destroy] resource :force_delete, controller: 'domains/force_delete', only: %i[create destroy]
resource :registry_lock, controller: 'domains/registry_lock', only: :destroy resource :registry_lock, controller: 'domains/registry_lock', only: :destroy
member do
patch :keep
end
end end
resources :domain_versions do resources :domain_versions do
@ -264,4 +268,4 @@ Rails.application.routes.draw do
# To prevent users seeing the default welcome message "Welcome aboard" from Rails # To prevent users seeing the default welcome message "Welcome aboard" from Rails
root to: redirect('admin/sign_in') root to: redirect('admin/sign_in')
end end

View file

@ -57,6 +57,10 @@ if @cron_group == 'registry'
every :day, at: '19:00pm' do every :day, at: '19:00pm' do
runner 'Directo.send_receipts' runner 'Directo.send_receipts'
end if @environment == 'production' end if @environment == 'production'
every 42.minutes do
rake 'domain:discard'
end
end end
every 10.minutes do every 10.minutes do

View file

@ -0,0 +1,5 @@
class ChangeContactsEmailToNotNull < ActiveRecord::Migration
def change
change_column_null :contacts, :email, false
end
end

View file

@ -613,7 +613,7 @@ CREATE TABLE public.contacts (
id integer NOT NULL, id integer NOT NULL,
code character varying NOT NULL, code character varying NOT NULL,
phone character varying, phone character varying,
email character varying, email character varying NOT NULL,
fax character varying, fax character varying,
created_at timestamp without time zone, created_at timestamp without time zone,
updated_at timestamp without time zone, updated_at timestamp without time zone,
@ -4764,5 +4764,7 @@ INSERT INTO schema_migrations (version) VALUES ('20180713154915');
INSERT INTO schema_migrations (version) VALUES ('20180808064402'); INSERT INTO schema_migrations (version) VALUES ('20180808064402');
INSERT INTO schema_migrations (version) VALUES ('20180816123540');
INSERT INTO schema_migrations (version) VALUES ('20180824092855'); INSERT INTO schema_migrations (version) VALUES ('20180824092855');

View file

@ -26,7 +26,10 @@ class AuthTokenCreator
def encrypted_token def encrypted_token
encryptor = OpenSSL::Cipher::AES.new(256, :CBC) encryptor = OpenSSL::Cipher::AES.new(256, :CBC)
encryptor.encrypt encryptor.encrypt
encryptor.key = key
# OpenSSL used to automatically shrink oversized keys, it does not do that any longer.
# See: https://github.com/ruby/openssl/issues/116
encryptor.key = key[0..31]
encrypted_bytes = encryptor.update(hashable) + encryptor.final encrypted_bytes = encryptor.update(hashable) + encryptor.final
Base64.urlsafe_encode64(encrypted_bytes) Base64.urlsafe_encode64(encrypted_bytes)
end end

View file

@ -16,7 +16,10 @@ class AuthTokenDecryptor
def decrypt_token def decrypt_token
decipher = OpenSSL::Cipher::AES.new(256, :CBC) decipher = OpenSSL::Cipher::AES.new(256, :CBC)
decipher.decrypt decipher.decrypt
decipher.key = key
# OpenSSL used to automatically shrink oversized keys, it does not do that any longer.
# See: https://github.com/ruby/openssl/issues/116
decipher.key = key[0..31]
base64_decoded = Base64.urlsafe_decode64(token.to_s) base64_decoded = Base64.urlsafe_decode64(token.to_s)
plain = decipher.update(base64_decoded) + decipher.final plain = decipher.update(base64_decoded) + decipher.final

13
lib/tasks/domain.rake Normal file
View file

@ -0,0 +1,13 @@
namespace :domain do
desc 'Discard domains'
task discard: :environment do
domain_count = 0
Domain.discard_domains do |domain|
puts "#{domain} is discarded"
domain_count = domain_count + 1
end
puts "Discarded total: #{domain_count}"
end
end

View file

@ -795,22 +795,6 @@ RSpec.describe Domain do
end end
end end
describe '::delete_candidates', db: true do
before :example do
travel_to Time.zone.parse('05.07.2010 00:00')
create(:zone, origin: 'ee')
create(:domain, id: 1, delete_time: Time.zone.parse('04.07.2010 23:59'))
create(:domain, id: 2, delete_time: Time.zone.parse('05.07.2010 00:00'))
create(:domain, id: 3, delete_time: Time.zone.parse('05.07.2010 00:01'))
end
it 'returns domains with delete time in the past' do
expect(described_class.delete_candidates.ids).to eq([1])
end
end
describe '::uses_zone?', db: true do describe '::uses_zone?', db: true do
let!(:zone) { create(:zone, origin: 'domain.tld') } let!(:zone) { create(:zone, origin: 'domain.tld') }

View file

@ -44,7 +44,7 @@ RSpec.describe DomainPresenter do
subject(:delete_date) { presenter.delete_date } subject(:delete_date) { presenter.delete_date }
context 'when present' do context 'when present' do
let(:domain) { instance_double(Domain, delete_time: '05.07.2010') } let(:domain) { instance_double(Domain, delete_at: '05.07.2010') }
it 'returns localized date' do it 'returns localized date' do
expect(view).to receive(:l).with('05.07.2010', format: :date).and_return('delete date') expect(view).to receive(:l).with('05.07.2010', format: :date).and_return('delete date')
@ -53,7 +53,7 @@ RSpec.describe DomainPresenter do
end end
context 'when absent' do context 'when absent' do
let(:domain) { instance_double(Domain, delete_time: nil) } let(:domain) { instance_double(Domain, delete_at: nil) }
specify { expect(delete_date).to be_nil } specify { expect(delete_date).to be_nil }
end end

View file

@ -1,6 +1,10 @@
require 'test_helper' require 'test_helper'
class EppDomainDeleteTest < ApplicationIntegrationTest class EppDomainDeleteTest < ApplicationIntegrationTest
def setup
@domain = domains(:shop)
end
def test_bypasses_domain_and_registrant_and_contacts_validation def test_bypasses_domain_and_registrant_and_contacts_validation
request_xml = <<-XML request_xml = <<-XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
@ -27,7 +31,9 @@ class EppDomainDeleteTest < ApplicationIntegrationTest
end end
def test_discarded_domain_cannot_be_deleted def test_discarded_domain_cannot_be_deleted
domains(:shop).discard travel_to Time.zone.parse('2010-07-05 10:30')
@domain.delete_at = Time.zone.parse('2010-07-05 10:00')
@domain.discard
request_xml = <<-XML request_xml = <<-XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
@ -51,5 +57,6 @@ class EppDomainDeleteTest < ApplicationIntegrationTest
post '/epp/command/delete', { frame: request_xml }, 'HTTP_COOKIE' => 'session=api_bestnames' post '/epp/command/delete', { frame: request_xml }, 'HTTP_COOKIE' => 'session=api_bestnames'
end end
assert_equal '2105', Nokogiri::XML(response.body).at_css('result')[:code] assert_equal '2105', Nokogiri::XML(response.body).at_css('result')[:code]
travel_back
end end
end end

View file

@ -1,6 +1,10 @@
require 'test_helper' require 'test_helper'
class EppDomainUpdateTest < ApplicationIntegrationTest class EppDomainUpdateTest < ApplicationIntegrationTest
def setup
@domain = domains(:shop)
end
def test_update_domain def test_update_domain
request_xml = <<-XML request_xml = <<-XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
@ -21,13 +25,16 @@ class EppDomainUpdateTest < ApplicationIntegrationTest
XML XML
post '/epp/command/update', { frame: request_xml }, 'HTTP_COOKIE' => 'session=api_bestnames' post '/epp/command/update', { frame: request_xml }, 'HTTP_COOKIE' => 'session=api_bestnames'
assert_equal 'f0ff7d17b0', domains(:shop).transfer_code @domain.reload
assert_equal 'f0ff7d17b0', @domain.transfer_code
assert_equal '1000', Nokogiri::XML(response.body).at_css('result')[:code] assert_equal '1000', Nokogiri::XML(response.body).at_css('result')[:code]
assert_equal 1, Nokogiri::XML(response.body).css('result').size assert_equal 1, Nokogiri::XML(response.body).css('result').size
end end
def test_discarded_domain_cannot_be_updated def test_discarded_domain_cannot_be_updated
domains(:shop).discard travel_to Time.zone.parse('2010-07-05 10:30')
@domain.delete_at = Time.zone.parse('2010-07-05 10:00')
@domain.discard
request_xml = <<-XML request_xml = <<-XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
@ -44,5 +51,6 @@ class EppDomainUpdateTest < ApplicationIntegrationTest
post '/epp/command/update', { frame: request_xml }, 'HTTP_COOKIE' => 'session=api_bestnames' post '/epp/command/update', { frame: request_xml }, 'HTTP_COOKIE' => 'session=api_bestnames'
assert_equal '2105', Nokogiri::XML(response.body).at_css('result')[:code] assert_equal '2105', Nokogiri::XML(response.body).at_css('result')[:code]
travel_back
end end
end end

View file

@ -1,12 +1,17 @@
require 'test_helper' require 'test_helper'
class EppDomainTransferRequestTest < ApplicationIntegrationTest class EppDomainTransferRequestTest < ApplicationIntegrationTest
setup do def setup
@domain = domains(:shop) @domain = domains(:shop)
@new_registrar = registrars(:goodnames) @new_registrar = registrars(:goodnames)
@original_transfer_wait_time = Setting.transfer_wait_time
Setting.transfer_wait_time = 0 Setting.transfer_wait_time = 0
end end
def teardown
Setting.transfer_wait_time = @original_transfer_wait_time
end
def test_transfers_domain_at_once def test_transfers_domain_at_once
post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' } post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
assert_equal '1000', Nokogiri::XML(response.body).at_css('result')[:code] assert_equal '1000', Nokogiri::XML(response.body).at_css('result')[:code]
@ -75,14 +80,17 @@ class EppDomainTransferRequestTest < ApplicationIntegrationTest
assert_equal '2304', Nokogiri::XML(response.body).at_css('result')[:code] assert_equal '2304', Nokogiri::XML(response.body).at_css('result')[:code]
end end
def test_discarded_domain def test_discarded_domain_cannot_be_transferred
@domain.update!(statuses: [DomainStatus::DELETE_CANDIDATE]) travel_to Time.zone.parse('2010-07-05 10:30')
@domain.delete_at = Time.zone.parse('2010-07-05 10:00')
@domain.discard
post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' } post '/epp/command/transfer', { frame: request_xml }, { 'HTTP_COOKIE' => 'session=api_goodnames' }
@domain.reload @domain.reload
assert_equal registrars(:bestnames), @domain.registrar assert_equal registrars(:bestnames), @domain.registrar
assert_equal '2105', Nokogiri::XML(response.body).at_css('result')[:code] assert_equal '2105', Nokogiri::XML(response.body).at_css('result')[:code]
travel_back
end end
def test_same_registrar def test_same_registrar

View file

@ -0,0 +1,51 @@
require 'test_helper'
class DiscardDomainTaskTest < TaskTestCase
setup do
travel_to Time.zone.parse('2010-07-05 08:00')
@domain = domains(:shop)
end
def test_discard_domains_with_past_delete_at
@domain.update!(delete_at: Time.zone.parse('2010-07-05 07:59'))
Rake::Task['domain:discard'].execute
@domain.reload
assert @domain.discarded?
end
def test_ignore_domains_with_delete_at_in_the_future_or_now
@domain.update!(delete_at: Time.zone.parse('2010-07-05 08:00'))
Rake::Task['domain:discard'].execute
@domain.reload
refute @domain.discarded?
end
def test_ignore_already_discarded_domains
@domain.update!(delete_at: Time.zone.parse('2010-07-05 07:59'))
@domain.discard
job_count = lambda do
QueJob.where("args->>0 = '#{@domain.id}'", job_class: DomainDeleteJob.name).count
end
assert_no_difference job_count, 'A domain should not be discarded again' do
Rake::Task['domain:discard'].execute
end
end
def test_ignore_domains_with_server_delete_prohibited_status
@domain.update!(delete_at: Time.zone.parse('2010-07-05 07:59'),
statuses: [DomainStatus::SERVER_DELETE_PROHIBITED])
Rake::Task['domain:discard'].execute
@domain.reload
refute @domain.discarded?
end
def test_show_results
@domain.update!(delete_at: Time.zone.parse('2010-07-05 07:59'))
$stdout = StringIO.new
Rake::Task['domain:discard'].execute
assert_equal "shop.test is discarded\nDiscarded total: 1\n", $stdout.string
end
end

View file

@ -8,7 +8,7 @@ class AuthTokenCreatorTest < ActiveSupport::TestCase
@user = users(:registrant) @user = users(:registrant)
time = Time.zone.parse('2010-07-05 00:30:00 +0000') time = Time.zone.parse('2010-07-05 00:30:00 +0000')
@random_bytes = SecureRandom.random_bytes(64) @random_bytes = SecureRandom.random_bytes(32)
@token_creator = AuthTokenCreator.new(@user, @random_bytes, time) @token_creator = AuthTokenCreator.new(@user, @random_bytes, time)
end end

View file

@ -1,14 +0,0 @@
require 'test_helper'
class DomainDeletableTest < ActiveSupport::TestCase
setup do
@domain = domains(:shop)
end
def test_discard
refute @domain.discarded?
@domain.discard
@domain.reload
assert @domain.discarded?
end
end

View file

@ -0,0 +1,63 @@
require 'test_helper'
class DomainDiscardableTest < ActiveSupport::TestCase
setup do
travel_to Time.zone.parse('2010-07-05 10:30')
@domain = domains(:shop)
@domain.delete_at = Time.zone.parse('2010-07-05 10:00')
end
teardown do
travel_back
end
def test_discarding_a_domain_persists_the_state
@domain.discard
@domain.reload
assert @domain.discarded?
end
def test_discarding_a_domain_schedules_deletion_at_random_time
@domain.discard
other_domain = domains(:airport)
other_domain.delete_at = Time.zone.parse('2010-07-04')
other_domain.discard
background_job = QueJob.find_by("args->>0 = '#{@domain.id}'", job_class: DomainDeleteJob.name)
other_background_job = QueJob.find_by("args->>0 = '#{other_domain.id}'",
job_class: DomainDeleteJob.name)
assert_not_equal background_job.run_at, other_background_job.run_at
end
def test_discarding_a_domain_bypasses_validation
domain = domains(:invalid)
domain.delete_at = Time.zone.parse('2010-07-05 10:00')
domain.discard
domain.reload
assert domain.discarded?
end
def test_domain_cannot_be_discarded_repeatedly
@domain.discard
exception = assert_raises do
@domain.discard
end
assert_equal 'Domain is already discarded', exception.message
end
def test_keeping_a_domain_bypasses_validation
domain = domains(:invalid)
domain.delete_at = Time.zone.parse('2010-07-05 10:00')
domain.discard
domain.keep
domain.reload
assert_not domain.discarded?
end
def test_keeping_a_domain_cancels_domain_deletion
@domain.discard
@domain.keep
assert_nil QueJob.find_by("args->>0 = '#{@domain.id}'", job_class: DomainDeleteJob.name)
end
end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class DomainForceDeleteTest < ActiveSupport::TestCase class DomainForceDeleteTest < ActiveSupport::TestCase
def setup setup do
@domain = domains(:shop) @domain = domains(:shop)
end end
@ -74,7 +74,7 @@ class DomainForceDeleteTest < ActiveSupport::TestCase
end end
def test_force_delete_cannot_be_scheduled_when_a_domain_is_discarded def test_force_delete_cannot_be_scheduled_when_a_domain_is_discarded
@domain.discard @domain.update!(statuses: [DomainStatus::DELETE_CANDIDATE])
assert_raises StandardError do assert_raises StandardError do
@domain.schedule_force_delete @domain.schedule_force_delete
end end

View file

@ -21,8 +21,8 @@ class ContactVersionsTest < ApplicationSystemTestCase
VALUES (75, 'test_registrar', 'test123', 'test@test.com', 'EE', 'TEST123', VALUES (75, 'test_registrar', 'test123', 'test@test.com', 'EE', 'TEST123',
'test123', 'en'); 'test123', 'en');
INSERT INTO contacts (id, code, auth_info, registrar_id) INSERT INTO contacts (id, code, email, auth_info, registrar_id)
VALUES (75, 'test_code', '8b4d462aa04194ca78840a', 75); VALUES (75, 'test_code', 'test@inbox.test', '8b4d462aa04194ca78840a', 75);
INSERT INTO log_contacts (item_type, item_id, event, whodunnit, object, INSERT INTO log_contacts (item_type, item_id, event, whodunnit, object,
object_changes, created_at, session, children, ident_updated_at, uuid) object_changes, created_at, session, children, ident_updated_at, uuid)

View file

@ -21,8 +21,8 @@ class DomainVersionsTest < ApplicationSystemTestCase
VALUES (54, 'test_registrar', 'test123', 'test@test.com', 'EE', 'TEST123', VALUES (54, 'test_registrar', 'test123', 'test@test.com', 'EE', 'TEST123',
'test123', 'en'); 'test123', 'en');
INSERT INTO contacts (id, code, auth_info, registrar_id) INSERT INTO contacts (id, code, email, auth_info, registrar_id)
VALUES (54, 'test_code', '8b4d462aa04194ca78840a', 54); VALUES (54, 'test_code', 'test@inbox.test', '8b4d462aa04194ca78840a', 54);
INSERT INTO domains (id, registrar_id, valid_to, registrant_id, INSERT INTO domains (id, registrar_id, valid_to, registrant_id,
transfer_code) transfer_code)

View file

@ -7,9 +7,14 @@ class AdminAreaDomainDetailsTest < ApplicationSystemTestCase
end end
def test_discarded_domain_has_corresponding_label def test_discarded_domain_has_corresponding_label
travel_to Time.zone.parse('2010-07-05 10:30')
@domain.delete_at = Time.zone.parse('2010-07-05 10:00')
visit admin_domain_url(@domain) visit admin_domain_url(@domain)
assert_no_css 'span.label.label-warning', text: 'deleteCandidate' assert_no_css 'span.label.label-warning', text: 'deleteCandidate'
@domain.discard @domain.discard
visit admin_domain_url(@domain) visit admin_domain_url(@domain)
assert_css 'span.label.label-warning', text: 'deleteCandidate' assert_css 'span.label.label-warning', text: 'deleteCandidate'
end end

View file

@ -56,7 +56,7 @@ class AdminAreaDomainForceDeleteTest < ApplicationSystemTestCase
end end
def test_force_delete_procedure_cannot_be_scheduled_on_a_discarded_domain def test_force_delete_procedure_cannot_be_scheduled_on_a_discarded_domain
@domain.discard @domain.update!(statuses: [DomainStatus::DELETE_CANDIDATE])
visit edit_admin_domain_url(@domain) visit edit_admin_domain_url(@domain)
assert_no_button 'Schedule force delete' assert_no_button 'Schedule force delete'

View file

@ -27,4 +27,17 @@ class AdminDomainsTestTest < ApplicationSystemTestCase
assert_text 'Registry lock time 2010-07-05 00:30' assert_text 'Registry lock time 2010-07-05 00:30'
assert_text 'registryLock' assert_text 'registryLock'
end end
def test_keep_a_domain
@domain.delete_at = Time.zone.parse('2010-07-05 10:00')
@domain.discard
visit edit_admin_domain_url(@domain)
click_link_or_button 'Remove deleteCandidate status'
@domain.reload
assert_not @domain.discarded?
assert_text 'deleteCandidate status has been removed'
assert_no_link 'Remove deleteCandidate status'
end
end end