diff --git a/.gitignore b/.gitignore
index 668b50574..ae8292f38 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,9 @@ todo
## Environment normalisation:
/.bundle
/vendor/bundle
+.idea
+# editor tmp files
+*.*~
# these should all be checked in to normalise the environment:
# Gemfile.lock, .ruby-version, .ruby-gemset
diff --git a/app/controllers/admin/domains_controller.rb b/app/controllers/admin/domains_controller.rb
index 7c90c1a49..3240db931 100644
--- a/app/controllers/admin/domains_controller.rb
+++ b/app/controllers/admin/domains_controller.rb
@@ -52,7 +52,7 @@ class Admin::DomainsController < AdminController
redirect_to [:admin, @domain]
else
build_associations
- flash.now[:alert] = I18n.t('failed_to_update_domain')
+ flash.now[:alert] = I18n.t('failed_to_update_domain') + ' ' + @domain.errors.full_messages.join(", ")
render 'edit'
end
end
diff --git a/app/controllers/epp/domains_controller.rb b/app/controllers/epp/domains_controller.rb
index 1e778b839..5b31a0dad 100644
--- a/app/controllers/epp/domains_controller.rb
+++ b/app/controllers/epp/domains_controller.rb
@@ -49,14 +49,17 @@ class Epp::DomainsController < EppController
def update
authorize! :update, @domain, @password
-
- if @domain.update(params[:parsed_frame], current_user)
- if @domain.epp_pending_update.present?
- render_epp_response '/epp/domains/success_pending'
+ begin
+ if @domain.update(params[:parsed_frame], current_user)
+ if @domain.epp_pending_update.present?
+ render_epp_response '/epp/domains/success_pending'
+ else
+ render_epp_response '/epp/domains/success'
+ end
else
- render_epp_response '/epp/domains/success'
+ handle_errors(@domain)
end
- else
+ rescue
handle_errors(@domain)
end
end
diff --git a/app/jobs/domain_delete_confirm_job.rb b/app/jobs/domain_delete_confirm_job.rb
index 9b30a6cbd..7d890ef16 100644
--- a/app/jobs/domain_delete_confirm_job.rb
+++ b/app/jobs/domain_delete_confirm_job.rb
@@ -10,6 +10,7 @@ class DomainDeleteConfirmJob < Que::Job
domain.clean_pendings!
when RegistrantVerification::REJECTED
DomainMailer.pending_delete_rejected_notification(domain).deliver_now
+ domain.statuses.delete(DomainStatus::PENDING_DELETE_CONFIRMATION)
domain.poll_message!(:poll_pending_delete_rejected_by_registrant)
domain.clean_pendings!
end
diff --git a/app/models/depp/user.rb b/app/models/depp/user.rb
index 44c25bbb1..51ce3f682 100644
--- a/app/models/depp/user.rb
+++ b/app/models/depp/user.rb
@@ -18,7 +18,7 @@ module Depp
def server
client_cert = File.read(ENV['cert_path'])
client_key = File.read(ENV['key_path'])
- port = Rails.env.test? ? 701 : ENV['epp_port']
+ port = ENV['epp_port'] || '700'
@server_cache ||= Epp::Server.new({
server: ENV['epp_hostname'],
diff --git a/app/models/domain.rb b/app/models/domain.rb
index 3ec4315d1..370d83a87 100644
--- a/app/models/domain.rb
+++ b/app/models/domain.rb
@@ -12,9 +12,14 @@ class Domain < ActiveRecord::Base
# TODO: should we user validates_associated :registrant here?
has_many :admin_domain_contacts
- accepts_nested_attributes_for :admin_domain_contacts, allow_destroy: true
+ accepts_nested_attributes_for :admin_domain_contacts, allow_destroy: !:admin_change_prohibited?, reject_if: :admin_change_prohibited?
has_many :tech_domain_contacts
- accepts_nested_attributes_for :tech_domain_contacts, allow_destroy: true
+ accepts_nested_attributes_for :tech_domain_contacts, allow_destroy: !:tech_change_prohibited?, reject_if: :tech_change_prohibited?
+
+ def registrant_change_prohibited?
+ statuses.include? DomainStatus::SERVER_REGISTRANT_CHANGE_PROHIBITED
+ end
+
# NB! contacts, admin_contacts, tech_contacts are empty for a new record
has_many :domain_contacts, dependent: :destroy
@@ -108,7 +113,15 @@ class Domain < ActiveRecord::Base
errors.add(:base, :invalid_auth_information_reserved)
end
- validate :check_permissions
+ validate :status_is_consistant
+ def status_is_consistant
+ has_error = (statuses.include?(DomainStatus::SERVER_HOLD) && statuses.include?(DomainStatus::SERVER_MANUAL_INZONE))
+ errors.add(:domains, I18n.t(:object_status_prohibits_operation)) if has_error
+ end
+
+ attr_accessor :is_admin
+
+ validate :check_permissions, :unless => :is_admin
def check_permissions
return unless force_delete?
errors.add(:base, I18n.t(:object_status_prohibits_operation))
@@ -174,6 +187,14 @@ class Domain < ActiveRecord::Base
nameservers.select { |x| !x.hostname.end_with?(name) }
end
+ def admin_change_prohibited?
+ statuses.include? DomainStatus::SERVER_ADMIN_CHANGE_PROHIBITED
+ end
+
+ def tech_change_prohibited?
+ statuses.include? DomainStatus::SERVER_TECH_CHANGE_PROHIBITED
+ end
+
class << self
def convert_period_to_time(period, unit)
return (period.to_i / 365).years if unit == 'd'
@@ -202,7 +223,7 @@ class Domain < ActiveRecord::Base
count = 0
expired_pending_domains = Domain.where('registrant_verification_asked_at <= ?', expire_at)
expired_pending_domains.each do |domain|
- unless domain.pending_update? || domain.pending_delete?
+ unless domain.pending_update? || domain.pending_delete? || pending_delete_confirmation?
msg = "#{Time.zone.now.utc} - ISSUE: DOMAIN #{domain.id}: #{domain.name} IS IN EXPIRED PENDING LIST, " \
"but no pendingDelete/pendingUpdate state present!\n"
STDOUT << msg unless Rails.env.test?
@@ -212,7 +233,7 @@ class Domain < ActiveRecord::Base
if domain.pending_update?
DomainMailer.pending_update_expired_notification_for_new_registrant(domain).deliver_now
end
- if domain.pending_delete?
+ if domain.pending_delete? || pending_delete_confirmation?
DomainMailer.pending_delete_expired_notification(domain).deliver_now
end
domain.clean_pendings!
@@ -358,8 +379,7 @@ class Domain < ActiveRecord::Base
return false if statuses.include_any?(DomainStatus::DELETE_CANDIDATE, DomainStatus::SERVER_RENEW_PROHIBITED,
DomainStatus::CLIENT_RENEW_PROHIBITED, DomainStatus::PENDING_RENEW,
DomainStatus::PENDING_TRANSFER, DomainStatus::PENDING_DELETE,
- DomainStatus::PENDING_UPDATE, 'pendingDeleteConfirmation')
-
+ DomainStatus::PENDING_UPDATE, DomainStatus::PENDING_DELETE_CONFIRMATION)
true
end
@@ -379,6 +399,7 @@ class Domain < ActiveRecord::Base
def clean_pendings!
preclean_pendings
self.pending_json = {}
+ statuses.delete[DomainStatus::PENDING_DELETE_CONFIRMATION]
statuses.delete(DomainStatus::PENDING_UPDATE)
statuses.delete(DomainStatus::PENDING_DELETE)
status_notes[DomainStatus::PENDING_UPDATE] = ''
@@ -461,8 +482,9 @@ class Domain < ActiveRecord::Base
return true if pending_delete?
self.epp_pending_delete = true # for epp
+ # TODO: if this were to ever return true, that would be wrong. EPP would report sucess pending
return true unless registrant_verification_asked?
- set_pending_delete
+ pending_delete_confirmation!
save(validate: false) # should check if this did succeed
DomainMailer.pending_deleted(self).deliver_now
@@ -639,7 +661,7 @@ class Domain < ActiveRecord::Base
statuses.include?(DomainStatus::PENDING_UPDATE) && !statuses.include?(DomainStatus::FORCE_DELETE)
end
- # public api
+ # depricated not used, not valid
def update_prohibited?
pending_update_prohibited? && pending_delete_prohibited?
end
@@ -651,6 +673,7 @@ class Domain < ActiveRecord::Base
def pending_update_prohibited?
(statuses_was & [
+ DomainStatus::PENDING_DELETE_CONFIRMATION,
DomainStatus::CLIENT_UPDATE_PROHIBITED,
DomainStatus::SERVER_UPDATE_PROHIBITED,
DomainStatus::PENDING_CREATE,
@@ -673,6 +696,14 @@ class Domain < ActiveRecord::Base
statuses.include?(DomainStatus::PENDING_DELETE) && !statuses.include?(DomainStatus::FORCE_DELETE)
end
+ def pending_delete_confirmation?
+ statuses.include? DomainStatus::PENDING_DELETE_CONFIRMATION
+ end
+
+ def pending_delete_confirmation!
+ statuses << DomainStatus::PENDING_DELETE_CONFIRMATION unless pending_delete_prohibited?
+ end
+
def pending_delete_prohibited?
(statuses_was & [
DomainStatus::CLIENT_DELETE_PROHIBITED,
diff --git a/app/models/domain_status.rb b/app/models/domain_status.rb
index 9f74b6c82..543ba0ff4 100644
--- a/app/models/domain_status.rb
+++ b/app/models/domain_status.rb
@@ -68,6 +68,7 @@ class DomainStatus < ActiveRecord::Base
SERVER_REGISTRANT_CHANGE_PROHIBITED = 'serverRegistrantChangeProhibited'
SERVER_ADMIN_CHANGE_PROHIBITED = 'serverAdminChangeProhibited'
SERVER_TECH_CHANGE_PROHIBITED = 'serverTechChangeProhibited'
+ PENDING_DELETE_CONFIRMATION = 'pendingDeleteConfirmation'
FORCE_DELETE = 'serverForceDelete'
DELETE_CANDIDATE = 'deleteCandidate'
EXPIRED = 'expired'
@@ -77,7 +78,7 @@ class DomainStatus < ActiveRecord::Base
CLIENT_DELETE_PROHIBITED, SERVER_DELETE_PROHIBITED, CLIENT_HOLD, SERVER_HOLD,
CLIENT_RENEW_PROHIBITED, SERVER_RENEW_PROHIBITED, CLIENT_TRANSFER_PROHIBITED,
SERVER_TRANSFER_PROHIBITED, CLIENT_UPDATE_PROHIBITED, SERVER_UPDATE_PROHIBITED,
- INACTIVE, OK, PENDING_CREATE, PENDING_DELETE, PENDING_RENEW, PENDING_TRANSFER,
+ INACTIVE, OK, PENDING_CREATE, PENDING_DELETE, PENDING_DELETE_CONFIRMATION, PENDING_RENEW, PENDING_TRANSFER,
PENDING_UPDATE, SERVER_MANUAL_INZONE, SERVER_REGISTRANT_CHANGE_PROHIBITED,
SERVER_ADMIN_CHANGE_PROHIBITED, SERVER_TECH_CHANGE_PROHIBITED, FORCE_DELETE,
DELETE_CANDIDATE, EXPIRED
@@ -121,18 +122,6 @@ class DomainStatus < ActiveRecord::Base
class << self
def admin_statuses
- # [
- # SERVER_HOLD,
- # # sync with admin_statuses_map
- # # SERVER_MANUAL_INZONE,
- # # SERVER_RENEW_PROHIBITED,
- # # SERVER_TRANSFER_PROHIBITED,
- # # SERVER_REGISTRANT_CHANGE_PROHIBITED,
- # # SERVER_ADMIN_CHANGE_PROHIBITED,
- # # SERVER_TECH_CHANGE_PROHIBITED,
- # SERVER_DELETE_PROHIBITED,
- # SERVER_UPDATE_PROHIBITED
- # ]
admin_statuses_map.map(&:second)
end
@@ -162,7 +151,8 @@ class DomainStatus < ActiveRecord::Base
PENDING_DELETE,
PENDING_RENEW,
PENDING_TRANSFER,
- PENDING_UPDATE
+ PENDING_UPDATE,
+ PENDING_DELETE_CONFIRMATION
]
end
end
diff --git a/app/models/epp/domain.rb b/app/models/epp/domain.rb
index f28b76767..4a446d25c 100644
--- a/app/models/epp/domain.rb
+++ b/app/models/epp/domain.rb
@@ -149,6 +149,9 @@ class Epp::Domain < Domain
code = frame.css('registrant').first.try(:text)
if code.present?
+ if action == 'chg' && registrant_change_prohibited?
+ add_epp_error('2304', nil, DomainStatus::SERVER_REGISTRANT_CHANGE_PROHIBITED, I18n.t(:object_status_prohibits_operation))
+ end
regt = Registrant.find_by(code: code)
if regt
at[:registrant_id] = regt.id
@@ -233,6 +236,11 @@ class Epp::Domain < Domain
def admin_domain_contacts_attrs(frame, action)
admin_attrs = domain_contact_attrs_from(frame, action, 'admin')
+ if action && !admin_attrs.empty? && admin_change_prohibited?
+ add_epp_error('2304', 'admin', DomainStatus::SERVER_ADMIN_CHANGE_PROHIBITED, I18n.t(:object_status_prohibits_operation))
+ return []
+ end
+
case action
when 'rem'
return destroy_attrs(admin_attrs, admin_domain_contacts)
@@ -244,6 +252,11 @@ class Epp::Domain < Domain
def tech_domain_contacts_attrs(frame, action)
tech_attrs = domain_contact_attrs_from(frame, action, 'tech')
+ if action && !tech_attrs.empty? && tech_change_prohibited?
+ add_epp_error('2304', 'tech', DomainStatus::SERVER_TECH_CHANGE_PROHIBITED, I18n.t(:object_status_prohibits_operation))
+ return []
+ end
+
case action
when 'rem'
return destroy_attrs(tech_attrs, tech_domain_contacts)
@@ -377,7 +390,6 @@ class Epp::Domain < Domain
def domain_statuses_attrs(frame, action)
status_list = domain_status_list_from(frame)
-
if action == 'rem'
to_destroy = []
status_list.each do |x|
@@ -424,20 +436,31 @@ class Epp::Domain < Domain
def update(frame, current_user, verify = true)
return super if frame.blank?
at = {}.with_indifferent_access
- at.deep_merge!(attrs_from(frame.css('chg'), current_user))
+ at.deep_merge!(attrs_from(frame.css('chg'), current_user, 'chg'))
at.deep_merge!(attrs_from(frame.css('rem'), current_user, 'rem'))
at_add = attrs_from(frame.css('add'), current_user)
at[:nameservers_attributes] += at_add[:nameservers_attributes]
- at[:admin_domain_contacts_attributes] += at_add[:admin_domain_contacts_attributes]
- at[:tech_domain_contacts_attributes] += at_add[:tech_domain_contacts_attributes]
+
+ if !at[:admin_domain_contacts_attributes].empty? && admin_change_prohibited?
+ add_epp_error('2304', 'admin', DomainStatus::SERVER_ADMIN_CHANGE_PROHIBITED, I18n.t(:object_status_prohibits_operation))
+ else
+ at[:admin_domain_contacts_attributes] += at_add[:admin_domain_contacts_attributes]
+ end
+
+ if !at[:tech_domain_contacts_attributes].empty? && tech_change_prohibited?
+ add_epp_error('2304', 'tech', DomainStatus::SERVER_TECH_CHANGE_PROHIBITED, I18n.t(:object_status_prohibits_operation))
+ else
+ at[:tech_domain_contacts_attributes] += at_add[:tech_domain_contacts_attributes]
+ end
+
at[:dnskeys_attributes] += at_add[:dnskeys_attributes]
at[:statuses] =
statuses - domain_statuses_attrs(frame.css('rem'), 'rem') + domain_statuses_attrs(frame.css('add'), 'add')
# at[:statuses] += at_add[:domain_statuses_attributes]
- if verify &&
+ if errors.empty? && verify &&
Setting.request_confrimation_on_registrant_change_enabled &&
frame.css('registrant').present? &&
frame.css('registrant').attr('verified').to_s.downcase != 'yes'
@@ -468,12 +491,12 @@ class Epp::Domain < Domain
def apply_pending_delete!
preclean_pendings
- user = ApiUser.find(pending_json['current_user_id'])
- frame = Nokogiri::XML(pending_json['frame'])
+ statuses.delete(DomainStatus::PENDING_DELETE_CONFIRMATION)
statuses.delete(DomainStatus::PENDING_DELETE)
DomainMailer.delete_confirmation(self).deliver_now
- clean_pendings! if epp_destroy(frame, user, false)
+ # TODO: confirm that this actually makes sense
+ clean_pendings! if valid? && set_pending_delete!
true
end
@@ -486,11 +509,10 @@ class Epp::Domain < Domain
)
end
- def epp_destroy(frame, user_id, verify = true)
+ def epp_destroy(frame, user_id)
return false unless valid?
- if verify &&
- Setting.request_confirmation_on_domain_deletion_enabled &&
+ if Setting.request_confirmation_on_domain_deletion_enabled &&
frame.css('delete').attr('verified').to_s.downcase != 'yes'
registrant_verification_asked!(frame.to_s, user_id)
@@ -753,6 +775,8 @@ class Epp::Domain < Domain
end
### ABILITIES ###
+
+ # depricated -- this is redundant TODO: try to remove
def can_be_deleted?
begin
errors.add(:base, :domain_status_prohibits_operation)
@@ -764,6 +788,7 @@ class Epp::Domain < Domain
def transferrable?
(statuses & [
+ DomainStatus::PENDING_DELETE_CONFIRMATION,
DomainStatus::PENDING_CREATE,
DomainStatus::PENDING_UPDATE,
DomainStatus::PENDING_DELETE,
diff --git a/config/initializers/pdfkit.rb b/config/initializers/pdfkit.rb
index b38887c6e..d7bbc64b8 100644
--- a/config/initializers/pdfkit.rb
+++ b/config/initializers/pdfkit.rb
@@ -1,5 +1,9 @@
PDFKit.configure do |config|
- config.wkhtmltopdf = "#{Rails.root}/vendor/bin/wkhtmltopdf"
+ installed = %x(which wkhtmltopdf).chomp
+ if installed == "" then
+ installed = "#{Rails.root}/vendor/bin/wkhtmltopdf"
+ end
+ config.wkhtmltopdf = installed
config.default_options = {
page_size: 'A4',
quiet: true
diff --git a/lib/schemas/domain-eis-1.0.xsd b/lib/schemas/domain-eis-1.0.xsd
index 222d3d6f4..eb2b420da 100644
--- a/lib/schemas/domain-eis-1.0.xsd
+++ b/lib/schemas/domain-eis-1.0.xsd
@@ -29,7 +29,7 @@
-->
-
+
@@ -133,6 +133,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -396,6 +412,10 @@
+
+
+
+
diff --git a/spec/models/domain_spec.rb b/spec/models/domain_spec.rb
index c8c5f1ddf..9dd0f1a48 100644
--- a/spec/models/domain_spec.rb
+++ b/spec/models/domain_spec.rb
@@ -64,10 +64,15 @@ describe Domain do
end
context 'with valid attributes' do
- before :all do
+ before :example do
@domain = Fabricate(:domain)
end
+ after do
+ @domain.delete
+ @domain = nil
+ end
+
it 'should be valid' do
@domain.valid?
@domain.errors.full_messages.should match_array([])
@@ -305,6 +310,108 @@ describe Domain do
])
end
+ it 'should should be manual in zone and held after force delete' do
+ @domain.valid?
+ @domain.outzone_at = Time.zone.now + 1.day # before redemption grace period
+ # what should this be?
+ # @domain.server_holdable?.should be true
+ @domain.statuses.include?(DomainStatus::SERVER_HOLD).should be false
+ @domain.statuses.include?(DomainStatus::SERVER_MANUAL_INZONE).should be false
+ @domain.set_force_delete
+ @domain.server_holdable?.should be false
+ @domain.statuses.include?(DomainStatus::SERVER_MANUAL_INZONE).should be true
+ @domain.statuses.include?(DomainStatus::SERVER_HOLD).should be false
+ end
+
+ it 'should not allow update after force delete' do
+ @domain.valid?
+ @domain.pending_update_prohibited?.should be false
+ @domain.update_prohibited?.should be false
+ @domain.set_force_delete
+ @domain.pending_update_prohibited?.should be true
+ @domain.update_prohibited?.should be true
+ end
+
+ context 'with time period settings' do
+ before :all do
+ @save_days_to_renew = Setting.days_to_renew_domain_before_expire
+ @save_warning_period = Setting.expire_warning_period
+ @save_grace_period = Setting.redemption_grace_period
+ end
+
+ after :all do
+ Setting.days_to_renew_domain_before_expire = @save_days_to_renew
+ Setting.expire_warning_period = @save_warning_period
+ Setting.redemption_grace_period = @save_grace_period
+ end
+
+ before :example do
+ @domain.valid?
+ end
+
+ context 'with no renewal limit, renew anytime' do
+ before do
+ Setting.days_to_renew_domain_before_expire = 0
+ end
+
+ it 'should always renew with no policy' do
+ @domain.renewable?.should be true
+ end
+
+ it 'should not allow to renew after force delete' do
+ @domain.set_force_delete
+ @domain.renewable?.should be false
+ end
+ end
+
+ context 'with renew policy' do
+ before :all do
+ @policy = 30
+ Setting.days_to_renew_domain_before_expire = @policy
+ end
+
+ it 'should not allow renew before policy' do
+ @domain.valid_to = Time.zone.now.beginning_of_day + @policy.days * 2
+ @domain.renewable?.should be false
+ end
+
+ context 'ready to renew' do
+ before { @domain.valid_to = Time.zone.now + (@policy - 2).days }
+
+ it 'should allow renew' do
+ @domain.renewable?.should be true
+ end
+
+ it 'should not allow to renew after force delete' do
+ @domain.set_force_delete
+ @domain.renewable?.should be false
+ end
+ end
+ end
+ end
+
+ it 'should start redemption grace period' do
+ Domain.start_redemption_grace_period
+ @domain.reload
+ @domain.statuses.include?(DomainStatus::SERVER_HOLD).should == false
+
+ @domain.outzone_at = Time.zone.now
+ @domain.statuses << DomainStatus::SERVER_MANUAL_INZONE # this prohibits server_hold
+ @domain.save
+
+ Domain.start_redemption_grace_period
+ @domain.reload
+ @domain.statuses.include?(DomainStatus::SERVER_HOLD).should == false
+
+ @domain.statuses = []
+ @domain.save
+
+ Domain.start_redemption_grace_period
+ @domain.reload
+ @domain.statuses.include?(DomainStatus::SERVER_HOLD).should == true
+ end
+
+
it 'should set expired status and update outzone_at and delete_at' do
domain = Fabricate(:domain)
domain.statuses.should == ['ok']
@@ -482,7 +589,7 @@ describe Domain do
end
context 'about registrant update confirm' do
- before :all do
+ before :example do
@domain.registrant_verification_token = 123
@domain.registrant_verification_asked_at = Time.zone.now
@domain.statuses << DomainStatus::PENDING_UPDATE
@@ -503,7 +610,7 @@ describe Domain do
end
context 'about registrant update confirm when domain is invalid' do
- before :all do
+ before :example do
@domain.registrant_verification_token = 123
@domain.registrant_verification_asked_at = Time.zone.now
@domain.statuses << DomainStatus::PENDING_UPDATE
diff --git a/spec/support/epp.rb b/spec/support/epp.rb
index 24a86e3d9..6d57e7d9e 100644
--- a/spec/support/epp.rb
+++ b/spec/support/epp.rb
@@ -92,8 +92,10 @@ module Epp
end
def server
+ port = ENV['epp_port'] || 700
+ hostname = ENV['epp_hostname'] || 'localhost'
# tag and password not in use, add those at login xml
- @server ||= Epp::Server.new({ server: 'localhost', port: 701, tag: '', password: '' })
+ @server ||= Epp::Server.new({ server: hostname, port: port, tag: '', password: '' })
end
def parse_response(raw)