mirror of
https://github.com/internetee/registry.git
synced 2025-05-29 17:10:08 +02:00
Admin contact statuses management #2477
This commit is contained in:
parent
1f85cec9ac
commit
601592aed1
23 changed files with 335 additions and 190 deletions
|
@ -11,9 +11,38 @@ class Admin::ContactsController < AdminController
|
||||||
render json: Contact.search_by_query(params[:q])
|
render json: Contact.search_by_query(params[:q])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
cp = ignore_empty_statuses
|
||||||
|
|
||||||
|
if @contact.update(cp)
|
||||||
|
flash[:notice] = I18n.t('contact_updated')
|
||||||
|
redirect_to [:admin, @contact]
|
||||||
|
else
|
||||||
|
flash.now[:alert] = I18n.t('failed_to_update_contact')
|
||||||
|
render 'edit'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_contact
|
def set_contact
|
||||||
@contact = Contact.includes(domains: :registrar).find(params[:id])
|
@contact = Contact.includes(domains: :registrar).find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def contact_params
|
||||||
|
if params[:contact]
|
||||||
|
params.require(:contact).permit({ statuses: [], status_notes_array: [] })
|
||||||
|
else
|
||||||
|
{ statuses: [] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def ignore_empty_statuses
|
||||||
|
dp = contact_params
|
||||||
|
dp[:statuses].reject!(&:blank?)
|
||||||
|
dp
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,10 +5,12 @@ class Contact < ActiveRecord::Base
|
||||||
belongs_to :registrar
|
belongs_to :registrar
|
||||||
has_many :domain_contacts
|
has_many :domain_contacts
|
||||||
has_many :domains, through: :domain_contacts
|
has_many :domains, through: :domain_contacts
|
||||||
has_many :statuses, class_name: 'ContactStatus', dependent: :destroy
|
|
||||||
has_many :legal_documents, as: :documentable
|
has_many :legal_documents, as: :documentable
|
||||||
has_many :registrant_domains, class_name: 'Domain', foreign_key: 'registrant_id' # when contant is registrant
|
has_many :registrant_domains, class_name: 'Domain', foreign_key: 'registrant_id' # when contant is registrant
|
||||||
|
|
||||||
|
# TODO: remove later
|
||||||
|
has_many :depricated_statuses, class_name: 'DepricatedContactStatus', dependent: :destroy
|
||||||
|
|
||||||
accepts_nested_attributes_for :legal_documents
|
accepts_nested_attributes_for :legal_documents
|
||||||
|
|
||||||
validates :name, :phone, :email, :ident, :ident_type,
|
validates :name, :phone, :email, :ident, :ident_type,
|
||||||
|
@ -26,6 +28,12 @@ class Contact < ActiveRecord::Base
|
||||||
format: { with: /\A[\w\-\:]*\Z/i, message: :invalid },
|
format: { with: /\A[\w\-\:]*\Z/i, message: :invalid },
|
||||||
length: { maximum: 100, message: :too_long_contact_code }
|
length: { maximum: 100, message: :too_long_contact_code }
|
||||||
validate :ident_valid_format?
|
validate :ident_valid_format?
|
||||||
|
validate :uniq_statuses?
|
||||||
|
|
||||||
|
after_initialize do
|
||||||
|
self.statuses = [] if statuses.nil?
|
||||||
|
self.status_notes = {} if status_notes.nil?
|
||||||
|
end
|
||||||
|
|
||||||
before_validation :set_ident_country_code
|
before_validation :set_ident_country_code
|
||||||
before_validation :prefix_code
|
before_validation :prefix_code
|
||||||
|
@ -37,10 +45,10 @@ class Contact < ActiveRecord::Base
|
||||||
ContactMailer.email_updated(self).deliver_now
|
ContactMailer.email_updated(self).deliver_now
|
||||||
end
|
end
|
||||||
|
|
||||||
after_save :manage_statuses
|
before_save :manage_statuses
|
||||||
def manage_statuses
|
def manage_statuses
|
||||||
ContactStatus.manage(statuses, self)
|
manage_linked
|
||||||
statuses.reload
|
manage_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
scope :current_registrars, ->(id) { where(registrar_id: id) }
|
scope :current_registrars, ->(id) { where(registrar_id: id) }
|
||||||
|
@ -58,6 +66,79 @@ class Contact < ActiveRecord::Base
|
||||||
|
|
||||||
attr_accessor :deliver_emails
|
attr_accessor :deliver_emails
|
||||||
|
|
||||||
|
#
|
||||||
|
# STATUSES
|
||||||
|
#
|
||||||
|
# Requests to delete the object MUST be rejected.
|
||||||
|
CLIENT_DELETE_PROHIBITED = 'clientDeleteProhibited'
|
||||||
|
SERVER_DELETE_PROHIBITED = 'serverDeleteProhibited'
|
||||||
|
|
||||||
|
# Requests to transfer the object MUST be rejected.
|
||||||
|
CLIENT_TRANSFER_PROHIBITED = 'clientTransferProhibited'
|
||||||
|
SERVER_TRANSFER_PROHIBITED = 'serverTransferProhibited'
|
||||||
|
|
||||||
|
# The contact object has at least one active association with
|
||||||
|
# another object, such as a domain object. Servers SHOULD provide
|
||||||
|
# services to determine existing object associations.
|
||||||
|
# "linked" status MAY be combined with any status.
|
||||||
|
LINKED = 'linked'
|
||||||
|
|
||||||
|
# This is the normal status value for an object that has no pending
|
||||||
|
# operations or prohibitions. This value is set and removed by the
|
||||||
|
# server as other status values are added or removed.
|
||||||
|
# "ok" status MAY only be combined with "linked" status.
|
||||||
|
OK = 'ok'
|
||||||
|
|
||||||
|
# Requests to update the object (other than to remove this status) MUST be rejected.
|
||||||
|
CLIENT_UPDATE_PROHIBITED = 'clientUpdateProhibited'
|
||||||
|
SERVER_UPDATE_PROHIBITED = 'serverUpdateProhibited'
|
||||||
|
|
||||||
|
# A transform command has been processed for the object, but the
|
||||||
|
# action has not been completed by the server. Server operators can
|
||||||
|
# delay action completion for a variety of reasons, such as to allow
|
||||||
|
# for human review or third-party action. A transform command that
|
||||||
|
# is processed, but whose requested action is pending, is noted with
|
||||||
|
# response code 1001.
|
||||||
|
# When the requested action has been completed, the pendingCreate,
|
||||||
|
# pendingDelete, pendingTransfer, or pendingUpdate status value MUST be
|
||||||
|
# removed. All clients involved in the transaction MUST be notified
|
||||||
|
# using a service message that the action has been completed and that
|
||||||
|
# the status of the object has changed.
|
||||||
|
# The pendingCreate, pendingDelete, pendingTransfer, and pendingUpdate
|
||||||
|
# status values MUST NOT be combined with each other.
|
||||||
|
PENDING_CREATE = 'pendingCreate'
|
||||||
|
# "pendingTransfer" status MUST NOT be combined with either
|
||||||
|
# "clientTransferProhibited" or "serverTransferProhibited" status.
|
||||||
|
PENDING_TRANSFER = 'pendingTransfer'
|
||||||
|
# "pendingUpdate" status MUST NOT be combined with either
|
||||||
|
# "clientUpdateProhibited" or "serverUpdateProhibited" status.
|
||||||
|
PENDING_UPDATE = 'pendingUpdate'
|
||||||
|
# "pendingDelete" MUST NOT be combined with either
|
||||||
|
# "clientDeleteProhibited" or "serverDeleteProhibited" status.
|
||||||
|
PENDING_DELETE = 'pendingDelete'
|
||||||
|
|
||||||
|
STATUSES = [
|
||||||
|
CLIENT_DELETE_PROHIBITED, SERVER_DELETE_PROHIBITED,
|
||||||
|
CLIENT_TRANSFER_PROHIBITED,
|
||||||
|
SERVER_TRANSFER_PROHIBITED, CLIENT_UPDATE_PROHIBITED, SERVER_UPDATE_PROHIBITED,
|
||||||
|
OK, PENDING_CREATE, PENDING_DELETE, PENDING_TRANSFER,
|
||||||
|
PENDING_UPDATE, LINKED
|
||||||
|
]
|
||||||
|
|
||||||
|
CLIENT_STATUSES = [
|
||||||
|
CLIENT_DELETE_PROHIBITED, CLIENT_TRANSFER_PROHIBITED,
|
||||||
|
CLIENT_UPDATE_PROHIBITED
|
||||||
|
]
|
||||||
|
|
||||||
|
SERVER_STATUSES = [
|
||||||
|
SERVER_UPDATE_PROHIBITED,
|
||||||
|
SERVER_DELETE_PROHIBITED,
|
||||||
|
SERVER_TRANSFER_PROHIBITED
|
||||||
|
]
|
||||||
|
#
|
||||||
|
# END OF STATUSES
|
||||||
|
#
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def search_by_query(query)
|
def search_by_query(query)
|
||||||
res = search(code_cont: query).result
|
res = search(code_cont: query).result
|
||||||
|
@ -83,6 +164,20 @@ class Contact < ActiveRecord::Base
|
||||||
def privs
|
def privs
|
||||||
where("ident_type = '#{PRIV}'")
|
where("ident_type = '#{PRIV}'")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def admin_statuses
|
||||||
|
[
|
||||||
|
SERVER_UPDATE_PROHIBITED,
|
||||||
|
SERVER_DELETE_PROHIBITED
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def admin_statuses_map
|
||||||
|
[
|
||||||
|
['UpdateProhibited', SERVER_UPDATE_PROHIBITED],
|
||||||
|
['DeleteProhibited', SERVER_DELETE_PROHIBITED]
|
||||||
|
]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def roid
|
def roid
|
||||||
|
@ -104,6 +199,12 @@ class Contact < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def uniq_statuses?
|
||||||
|
return true unless statuses.detect { |s| statuses.count(s) > 1 }
|
||||||
|
errors.add(:statuses, :not_uniq)
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
def bic?
|
def bic?
|
||||||
ident_type == BIC
|
ident_type == BIC
|
||||||
end
|
end
|
||||||
|
@ -206,4 +307,48 @@ class Contact < ActiveRecord::Base
|
||||||
|
|
||||||
@desc
|
@desc
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def status_notes_array=(notes)
|
||||||
|
self.status_notes = {}
|
||||||
|
notes ||= []
|
||||||
|
statuses.each_with_index do |status,i|
|
||||||
|
self.status_notes[status] = notes[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def manage_linked
|
||||||
|
if domains.present?
|
||||||
|
statuses << LINKED if statuses.detect { |s| s == LINKED }.blank?
|
||||||
|
else
|
||||||
|
statuses.delete_if { |s| s == LINKED }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# rubocop:disable Metrics/CyclomaticComplexity
|
||||||
|
def manage_ok
|
||||||
|
return unset_ok unless valid?
|
||||||
|
|
||||||
|
case statuses.size
|
||||||
|
when 0
|
||||||
|
set_ok
|
||||||
|
when 1
|
||||||
|
set_ok if statuses == [LINKED]
|
||||||
|
when 2
|
||||||
|
return if statuses.sort == [LINKED, OK]
|
||||||
|
unset_ok
|
||||||
|
else
|
||||||
|
unset_ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# rubocop:enable Metrics/CyclomaticComplexity
|
||||||
|
|
||||||
|
def unset_ok
|
||||||
|
statuses.delete_if { |s| s == OK }
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_ok
|
||||||
|
statuses << OK if statuses.detect { |s| s == OK }.blank?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,124 +0,0 @@
|
||||||
class ContactStatus < ActiveRecord::Base
|
|
||||||
include Versions # version/contact_status_version.rb
|
|
||||||
include EppErrors
|
|
||||||
|
|
||||||
belongs_to :contact
|
|
||||||
|
|
||||||
# Requests to delete the object MUST be rejected.
|
|
||||||
CLIENT_DELETE_PROHIBITED = 'clientDeleteProhibited'
|
|
||||||
SERVER_DELETE_PROHIBITED = 'serverDeleteProhibited'
|
|
||||||
|
|
||||||
# Requests to transfer the object MUST be rejected.
|
|
||||||
CLIENT_TRANSFER_PROHIBITED = 'clientTransferProhibited'
|
|
||||||
SERVER_TRANSFER_PROHIBITED = 'serverTransferProhibited'
|
|
||||||
|
|
||||||
# The contact object has at least one active association with
|
|
||||||
# another object, such as a domain object. Servers SHOULD provide
|
|
||||||
# services to determine existing object associations.
|
|
||||||
# "linked" status MAY be combined with any status.
|
|
||||||
LINKED = 'linked'
|
|
||||||
|
|
||||||
# This is the normal status value for an object that has no pending
|
|
||||||
# operations or prohibitions. This value is set and removed by the
|
|
||||||
# server as other status values are added or removed.
|
|
||||||
# "ok" status MAY only be combined with "linked" status.
|
|
||||||
OK = 'ok'
|
|
||||||
|
|
||||||
# Requests to update the object (other than to remove this status) MUST be rejected.
|
|
||||||
CLIENT_UPDATE_PROHIBITED = 'clientUpdateProhibited'
|
|
||||||
SERVER_UPDATE_PROHIBITED = 'serverUpdateProhibited'
|
|
||||||
|
|
||||||
# A transform command has been processed for the object, but the
|
|
||||||
# action has not been completed by the server. Server operators can
|
|
||||||
# delay action completion for a variety of reasons, such as to allow
|
|
||||||
# for human review or third-party action. A transform command that
|
|
||||||
# is processed, but whose requested action is pending, is noted with
|
|
||||||
# response code 1001.
|
|
||||||
# When the requested action has been completed, the pendingCreate,
|
|
||||||
# pendingDelete, pendingTransfer, or pendingUpdate status value MUST be
|
|
||||||
# removed. All clients involved in the transaction MUST be notified
|
|
||||||
# using a service message that the action has been completed and that
|
|
||||||
# the status of the object has changed.
|
|
||||||
# The pendingCreate, pendingDelete, pendingTransfer, and pendingUpdate
|
|
||||||
# status values MUST NOT be combined with each other.
|
|
||||||
PENDING_CREATE = 'pendingCreate'
|
|
||||||
# "pendingTransfer" status MUST NOT be combined with either
|
|
||||||
# "clientTransferProhibited" or "serverTransferProhibited" status.
|
|
||||||
PENDING_TRANSFER = 'pendingTransfer'
|
|
||||||
# "pendingUpdate" status MUST NOT be combined with either
|
|
||||||
# "clientUpdateProhibited" or "serverUpdateProhibited" status.
|
|
||||||
PENDING_UPDATE = 'pendingUpdate'
|
|
||||||
# "pendingDelete" MUST NOT be combined with either
|
|
||||||
# "clientDeleteProhibited" or "serverDeleteProhibited" status.
|
|
||||||
PENDING_DELETE = 'pendingDelete'
|
|
||||||
|
|
||||||
STATUSES = [
|
|
||||||
CLIENT_DELETE_PROHIBITED, SERVER_DELETE_PROHIBITED,
|
|
||||||
CLIENT_TRANSFER_PROHIBITED,
|
|
||||||
SERVER_TRANSFER_PROHIBITED, CLIENT_UPDATE_PROHIBITED, SERVER_UPDATE_PROHIBITED,
|
|
||||||
OK, PENDING_CREATE, PENDING_DELETE, PENDING_TRANSFER,
|
|
||||||
PENDING_UPDATE, LINKED
|
|
||||||
]
|
|
||||||
|
|
||||||
CLIENT_STATUSES = [
|
|
||||||
CLIENT_DELETE_PROHIBITED, CLIENT_TRANSFER_PROHIBITED,
|
|
||||||
CLIENT_UPDATE_PROHIBITED
|
|
||||||
]
|
|
||||||
|
|
||||||
SERVER_STATUSES = [
|
|
||||||
SERVER_DELETE_PROHIBITED, SERVER_TRANSFER_PROHIBITED,
|
|
||||||
SERVER_UPDATE_PROHIBITED
|
|
||||||
]
|
|
||||||
|
|
||||||
class << self
|
|
||||||
def manage(statuses, contact)
|
|
||||||
manage_linked(statuses, contact)
|
|
||||||
manage_ok(statuses, contact)
|
|
||||||
end
|
|
||||||
|
|
||||||
def manage_linked(statuses, contact)
|
|
||||||
if contact.domains.present?
|
|
||||||
create(value: LINKED, contact_id: contact.id) if statuses.select { |s| s.value == LINKED }.blank?
|
|
||||||
else
|
|
||||||
statuses.select { |s| s.value == LINKED }.each(&:destroy)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def manage_ok(statuses, contact)
|
|
||||||
if statuses.present?
|
|
||||||
if contact.valid?
|
|
||||||
else
|
|
||||||
statuses.select { |s| s.value == OK }.each(&:destroy)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
create(value: OK, contact_id: contact.id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def epp_code_map
|
|
||||||
{
|
|
||||||
'2302' => [ # Object exists
|
|
||||||
[:value, :taken, { value: { obj: 'status', val: value } }]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def server_status?
|
|
||||||
SERVER_STATUSES.include?(value)
|
|
||||||
end
|
|
||||||
|
|
||||||
def client_status?
|
|
||||||
CLIENT_STATUSES.include?(value)
|
|
||||||
end
|
|
||||||
|
|
||||||
class << self
|
|
||||||
def statuses_for_client
|
|
||||||
CLIENT_STATUSES.map { |x| x.sub('client', '') }
|
|
||||||
end
|
|
||||||
|
|
||||||
def statuses_for_admin
|
|
||||||
SERVER_STATUSES.map { |x| x.sub('server', '') }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
5
app/models/depricated_contact_status.rb
Normal file
5
app/models/depricated_contact_status.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class DepricatedContactStatus < ActiveRecord::Base
|
||||||
|
self.table_name = :contact_statuses
|
||||||
|
self.sequence_name = :contact_statuses_id_seq
|
||||||
|
belongs_to :contact
|
||||||
|
end
|
|
@ -54,9 +54,10 @@ class Domain < ActiveRecord::Base
|
||||||
delegate :name, to: :registrar, prefix: true
|
delegate :name, to: :registrar, prefix: true
|
||||||
delegate :street, to: :registrar, prefix: true
|
delegate :street, to: :registrar, prefix: true
|
||||||
|
|
||||||
after_initialize :init_default_values
|
after_initialize do
|
||||||
def init_default_values
|
|
||||||
self.pending_json = {} if pending_json.blank?
|
self.pending_json = {} if pending_json.blank?
|
||||||
|
self.statuses = [] if statuses.nil?
|
||||||
|
self.status_notes = {} if status_notes.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
before_create :generate_auth_info
|
before_create :generate_auth_info
|
||||||
|
@ -77,7 +78,6 @@ class Domain < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
after_save :update_whois_record
|
after_save :update_whois_record
|
||||||
|
|
||||||
after_initialize -> { self.statuses = [] if statuses.nil? }
|
|
||||||
|
|
||||||
after_create :update_reserved_domains
|
after_create :update_reserved_domains
|
||||||
def update_reserved_domains
|
def update_reserved_domains
|
||||||
|
|
|
@ -484,7 +484,7 @@ class Epp::Domain < Domain
|
||||||
|
|
||||||
def copy_and_transfer_contact(contact_id, registrar_id)
|
def copy_and_transfer_contact(contact_id, registrar_id)
|
||||||
c = Contact.find(contact_id) # n+1 workaround
|
c = Contact.find(contact_id) # n+1 workaround
|
||||||
oc = c.deep_clone include: [:statuses]
|
oc = c.deep_clone
|
||||||
oc.code = nil
|
oc.code = nil
|
||||||
oc.registrar_id = registrar_id
|
oc.registrar_id = registrar_id
|
||||||
oc.prefix_code
|
oc.prefix_code
|
||||||
|
|
11
app/views/admin/contacts/_form.haml
Normal file
11
app/views/admin/contacts/_form.haml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
= form_for([:admin, contact], html: { class: 'form-horizontal' }) do |f|
|
||||||
|
.errors
|
||||||
|
= render 'shared/errors', object: contact
|
||||||
|
.row
|
||||||
|
.col-md-8
|
||||||
|
.tab-content{style:'margin-top: 20px;'}
|
||||||
|
#general-tab.tab-pane.active
|
||||||
|
= render 'admin/contacts/form_partials/statuses', f: f
|
||||||
|
.row
|
||||||
|
.col-md-8.text-right
|
||||||
|
= button_tag(t(:save), class: 'btn btn-primary')
|
6
app/views/admin/contacts/edit.haml
Normal file
6
app/views/admin/contacts/edit.haml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
- content_for :actions do
|
||||||
|
= link_to(t(:add_new_status), '#', class: 'btn btn-primary js-add-contact-status')
|
||||||
|
= link_to(t(:back_to_contact), [:admin, @contact], class: 'btn btn-default')
|
||||||
|
= render 'shared/title', name: "#{t(:edit)}: #{@contact.name}"
|
||||||
|
|
||||||
|
= render 'form', contact: @contact
|
41
app/views/admin/contacts/form_partials/_statuses.haml
Normal file
41
app/views/admin/contacts/form_partials/_statuses.haml
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#js-contact-statuses
|
||||||
|
- f.object.statuses.each do |s|
|
||||||
|
- disabled = !Contact.admin_statuses.include?(s)
|
||||||
|
- disabled_style = disabled ? 'display: none' : ''
|
||||||
|
- delete_style = [Contact::OK, Contact::LINKED].include?(s) ? 'display: none' : ''
|
||||||
|
|
||||||
|
.panel.panel-default
|
||||||
|
.panel-heading.clearfix
|
||||||
|
.pull-left= t(:status)
|
||||||
|
.pull-right
|
||||||
|
= link_to(t(:delete), '#', class: 'btn btn-danger btn-xs js-destroy-status', style: delete_style)
|
||||||
|
.panel-body
|
||||||
|
.form-group
|
||||||
|
= f.label 'status', class: 'col-md-2 control-label'
|
||||||
|
.col-md-10
|
||||||
|
.js-select{style: disabled_style}
|
||||||
|
= select_tag 'contact[statuses][]',
|
||||||
|
options_for_select(Contact::admin_statuses_map, s),
|
||||||
|
include_blank: true, class: "form-control"
|
||||||
|
- if disabled
|
||||||
|
.disabled-value.js-disabled-value
|
||||||
|
= s
|
||||||
|
= hidden_field_tag 'contact[statuses][]', s, readonly: true
|
||||||
|
.form-group
|
||||||
|
= label_tag t(:notes), nil, class: 'col-md-2 control-label'
|
||||||
|
.col-md-10
|
||||||
|
- value = f.object.new_record? ? '' : f.object.status_notes[s]
|
||||||
|
= text_field_tag 'contact[status_notes_array][]', value, class: 'form-control'
|
||||||
|
|
||||||
|
:coffee
|
||||||
|
$("#js-contact-statuses").nestedAttributes
|
||||||
|
bindAddTo: $(".js-add-contact-status")
|
||||||
|
afterAdd: (el) ->
|
||||||
|
if el.find('.js-disabled-value')
|
||||||
|
el.find('.js-disabled-value').remove()
|
||||||
|
el.find('.js-select').show()
|
||||||
|
el.find('.js-destroy-status').show()
|
||||||
|
|
||||||
|
$(document).on 'click', '.js-destroy-status', (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
$(this).parents('.panel').remove()
|
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
%br
|
%br
|
||||||
|
|
||||||
|
|
||||||
%dt= t(:ident)
|
%dt= t(:ident)
|
||||||
%dd= ident_for(@contact)
|
%dd= ident_for(@contact)
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
%thead
|
%thead
|
||||||
%tr
|
%tr
|
||||||
%th{class: 'col-xs-6'}= t(:status)
|
%th{class: 'col-xs-6'}= t(:status)
|
||||||
%th{class: 'col-xs-6'}= t(:description)
|
%th{class: 'col-xs-6'}= t(:notes)
|
||||||
%tbody
|
%tbody
|
||||||
- contact.statuses.each do |s|
|
- contact.statuses.each do |status|
|
||||||
%tr
|
%tr
|
||||||
%td= s.value
|
%td= status
|
||||||
%td= s.description
|
%td= contact.status_notes[status]
|
||||||
|
|
||||||
- if contact.errors.messages[:statuses]
|
- if contact.errors.messages[:statuses]
|
||||||
%tfoot
|
%tfoot
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
- content_for :actions do
|
||||||
|
= link_to(t(:edit_statuses), edit_admin_contact_path(@contact), class: 'btn btn-primary')
|
||||||
= render 'shared/title', name: @contact.name
|
= render 'shared/title', name: @contact.name
|
||||||
|
|
||||||
.row
|
.row
|
||||||
|
|
|
@ -10,7 +10,3 @@
|
||||||
.row
|
.row
|
||||||
.col-md-8.text-right
|
.col-md-8.text-right
|
||||||
= button_tag(t(:save), class: 'btn btn-primary')
|
= button_tag(t(:save), class: 'btn btn-primary')
|
||||||
|
|
||||||
:coffee
|
|
||||||
$ ->
|
|
||||||
$("#tabs a:first").tab "show"
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ xml.epp_head do
|
||||||
xml.tag!('contact:roid', @contact.roid)
|
xml.tag!('contact:roid', @contact.roid)
|
||||||
|
|
||||||
@contact.statuses.each do |status|
|
@contact.statuses.each do |status|
|
||||||
xml.tag!('contact:status', s: status.value)
|
xml.tag!('contact:status', s: status)
|
||||||
end
|
end
|
||||||
|
|
||||||
xml.tag!('contact:postalInfo', type: 'int') do
|
xml.tag!('contact:postalInfo', type: 'int') do
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
- object.errors.each do |attr, err|
|
- object.errors.each do |attr, err|
|
||||||
- next if attr.match(/\./)
|
- next if attr.match(/\./)
|
||||||
- next if attr == :epp_errors
|
- next if attr == :epp_errors
|
||||||
= err
|
= "#{attr.to_s.humanize} #{err}"
|
||||||
%br
|
%br
|
||||||
|
|
|
@ -44,7 +44,7 @@ Rails.application.configure do
|
||||||
|
|
||||||
# The available log levels are: :debug, :info, :warn, :error, :fatal, and :unknown,
|
# The available log levels are: :debug, :info, :warn, :error, :fatal, and :unknown,
|
||||||
# corresponding to the log level numbers from 0 up to 5 respectively
|
# corresponding to the log level numbers from 0 up to 5 respectively
|
||||||
config.log_level = :fatal
|
config.log_level = :info
|
||||||
|
|
||||||
# for finding database optimization
|
# for finding database optimization
|
||||||
config.after_initialize do
|
config.after_initialize do
|
||||||
|
|
|
@ -52,6 +52,8 @@ en:
|
||||||
invalid_country_code: "Ident country code is not valid, should be in ISO_3166-1 alpha 2 format"
|
invalid_country_code: "Ident country code is not valid, should be in ISO_3166-1 alpha 2 format"
|
||||||
domains:
|
domains:
|
||||||
exist: 'Object association prohibits operation'
|
exist: 'Object association prohibits operation'
|
||||||
|
statuses:
|
||||||
|
not_uniq: 'not uniq'
|
||||||
|
|
||||||
epp_domain: &epp_domain_ar_attributes
|
epp_domain: &epp_domain_ar_attributes
|
||||||
attributes:
|
attributes:
|
||||||
|
@ -874,3 +876,4 @@ en:
|
||||||
domain_registrant_updated: 'Domeeni %{name} registreerija vahetus teostatud / Registrant change of %{name} has been finished.'
|
domain_registrant_updated: 'Domeeni %{name} registreerija vahetus teostatud / Registrant change of %{name} has been finished.'
|
||||||
api_user_not_found: 'API user not found'
|
api_user_not_found: 'API user not found'
|
||||||
domain_already_belongs_to_the_querying_registrar: 'Domain already belongs to the querying registrar'
|
domain_already_belongs_to_the_querying_registrar: 'Domain already belongs to the querying registrar'
|
||||||
|
notes: Notes
|
||||||
|
|
15
db/data/20150707103801_refactor_contact_statuses.rb
Normal file
15
db/data/20150707103801_refactor_contact_statuses.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
class RefactorContactStatuses < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
Contact.find_each do |contact|
|
||||||
|
statuses = []
|
||||||
|
contact.depricated_statuses.each do |ds|
|
||||||
|
statuses << ds.value
|
||||||
|
end
|
||||||
|
contact.update_column('statuses', statuses)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
raise ActiveRecord::IrreversibleMigration
|
||||||
|
end
|
||||||
|
end
|
5
db/migrate/20150707103241_add_statuses_to_contact.rb
Normal file
5
db/migrate/20150707103241_add_statuses_to_contact.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class AddStatusesToContact < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :contacts, :statuses, :string, array: true
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,6 @@
|
||||||
|
class AddContactAndDomainStatusNotes < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :contacts, :status_notes, :hstore
|
||||||
|
add_column :domains, :status_notes, :hstore
|
||||||
|
end
|
||||||
|
end
|
|
@ -11,7 +11,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 20150713113436) do
|
ActiveRecord::Schema.define(version: 20150722071128) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
@ -200,6 +200,7 @@ ActiveRecord::Schema.define(version: 20150713113436) do
|
||||||
t.string "state"
|
t.string "state"
|
||||||
t.integer "legacy_id"
|
t.integer "legacy_id"
|
||||||
t.string "statuses", array: true
|
t.string "statuses", array: true
|
||||||
|
t.hstore "status_notes"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "contacts", ["code"], name: "index_contacts_on_code", using: :btree
|
add_index "contacts", ["code"], name: "index_contacts_on_code", using: :btree
|
||||||
|
@ -215,12 +216,6 @@ ActiveRecord::Schema.define(version: 20150713113436) do
|
||||||
t.string "updator_str"
|
t.string "updator_str"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "data_migrations", id: false, force: :cascade do |t|
|
|
||||||
t.string "version", null: false
|
|
||||||
end
|
|
||||||
|
|
||||||
add_index "data_migrations", ["version"], name: "unique_data_migrations", unique: true, using: :btree
|
|
||||||
|
|
||||||
create_table "delegation_signers", force: :cascade do |t|
|
create_table "delegation_signers", force: :cascade do |t|
|
||||||
t.integer "domain_id"
|
t.integer "domain_id"
|
||||||
t.string "key_tag"
|
t.string "key_tag"
|
||||||
|
@ -327,6 +322,7 @@ ActiveRecord::Schema.define(version: 20150713113436) do
|
||||||
t.datetime "force_delete_at"
|
t.datetime "force_delete_at"
|
||||||
t.string "statuses", array: true
|
t.string "statuses", array: true
|
||||||
t.boolean "reserved", default: false
|
t.boolean "reserved", default: false
|
||||||
|
t.hstore "status_notes"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "domains", ["delete_at"], name: "index_domains_on_delete_at", using: :btree
|
add_index "domains", ["delete_at"], name: "index_domains_on_delete_at", using: :btree
|
||||||
|
|
|
@ -632,7 +632,8 @@ CREATE TABLE contacts (
|
||||||
country_code character varying,
|
country_code character varying,
|
||||||
state character varying,
|
state character varying,
|
||||||
legacy_id integer,
|
legacy_id integer,
|
||||||
statuses character varying[]
|
statuses character varying[],
|
||||||
|
status_notes hstore
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -689,15 +690,6 @@ CREATE SEQUENCE countries_id_seq
|
||||||
ALTER SEQUENCE countries_id_seq OWNED BY countries.id;
|
ALTER SEQUENCE countries_id_seq OWNED BY countries.id;
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: data_migrations; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE data_migrations (
|
|
||||||
version character varying NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: delegation_signers; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
-- Name: delegation_signers; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
|
@ -945,7 +937,8 @@ CREATE TABLE domains (
|
||||||
pending_json json,
|
pending_json json,
|
||||||
force_delete_at timestamp without time zone,
|
force_delete_at timestamp without time zone,
|
||||||
statuses character varying[],
|
statuses character varying[],
|
||||||
reserved boolean DEFAULT false
|
reserved boolean DEFAULT false,
|
||||||
|
status_notes hstore
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -4519,13 +4512,6 @@ CREATE INDEX index_whois_records_on_domain_id ON whois_records USING btree (doma
|
||||||
CREATE INDEX index_whois_records_on_registrar_id ON whois_records USING btree (registrar_id);
|
CREATE INDEX index_whois_records_on_registrar_id ON whois_records USING btree (registrar_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: unique_data_migrations; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX unique_data_migrations ON data_migrations USING btree (version);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
-- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
|
@ -4861,10 +4847,6 @@ INSERT INTO schema_migrations (version) VALUES ('20150522164020');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150525075550');
|
INSERT INTO schema_migrations (version) VALUES ('20150525075550');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150601083516');
|
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150601083800');
|
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150603141054');
|
INSERT INTO schema_migrations (version) VALUES ('20150603141054');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150603141549');
|
INSERT INTO schema_migrations (version) VALUES ('20150603141549');
|
||||||
|
@ -4873,12 +4855,8 @@ INSERT INTO schema_migrations (version) VALUES ('20150603211318');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150603212659');
|
INSERT INTO schema_migrations (version) VALUES ('20150603212659');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150609093515');
|
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150609103333');
|
INSERT INTO schema_migrations (version) VALUES ('20150609103333');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150610111019');
|
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150610112238');
|
INSERT INTO schema_migrations (version) VALUES ('20150610112238');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150610144547');
|
INSERT INTO schema_migrations (version) VALUES ('20150610144547');
|
||||||
|
@ -4887,8 +4865,6 @@ INSERT INTO schema_migrations (version) VALUES ('20150611124920');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150612123111');
|
INSERT INTO schema_migrations (version) VALUES ('20150612123111');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150612125720');
|
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150701074344');
|
INSERT INTO schema_migrations (version) VALUES ('20150701074344');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150703084632');
|
INSERT INTO schema_migrations (version) VALUES ('20150703084632');
|
||||||
|
@ -4897,8 +4873,6 @@ INSERT INTO schema_migrations (version) VALUES ('20150706091724');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150707103241');
|
INSERT INTO schema_migrations (version) VALUES ('20150707103241');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150707103801');
|
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150707104937');
|
INSERT INTO schema_migrations (version) VALUES ('20150707104937');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150707154543');
|
INSERT INTO schema_migrations (version) VALUES ('20150707154543');
|
||||||
|
@ -4907,3 +4881,5 @@ INSERT INTO schema_migrations (version) VALUES ('20150709092549');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20150713113436');
|
INSERT INTO schema_migrations (version) VALUES ('20150713113436');
|
||||||
|
|
||||||
|
INSERT INTO schema_migrations (version) VALUES ('20150722071128');
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,12 @@ describe Contact do
|
||||||
@contact.errors[:code].should == ['Contact code is too long, max 100 characters']
|
@contact.errors[:code].should == ['Contact code is too long, max 100 characters']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'should not allow double status' do
|
||||||
|
@contact.statuses = ['ok', 'ok']
|
||||||
|
@contact.valid?
|
||||||
|
@contact.errors[:statuses].should == ['not uniq']
|
||||||
|
end
|
||||||
|
|
||||||
it 'should have no related domain descriptions' do
|
it 'should have no related domain descriptions' do
|
||||||
@contact.related_domain_descriptions.should == {}
|
@contact.related_domain_descriptions.should == {}
|
||||||
end
|
end
|
||||||
|
@ -154,17 +160,36 @@ describe Contact do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should have ok status by default' do
|
it 'should have ok status by default' do
|
||||||
@contact.statuses.size.should == 1
|
@contact.statuses.should == %w(ok)
|
||||||
@contact.statuses.first.value.should == 'ok'
|
end
|
||||||
|
|
||||||
|
it 'should not remove ok status after save' do
|
||||||
|
@contact.statuses.should == %w(ok)
|
||||||
|
@contact.save
|
||||||
|
@contact.statuses.should == %w(ok)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should remove ok status when other non linked status present' do
|
||||||
|
contact = Fabricate(:contact)
|
||||||
|
contact.statuses = [Contact::SERVER_UPDATE_PROHIBITED]
|
||||||
|
contact.statuses.should == [Contact::SERVER_UPDATE_PROHIBITED] # temp test
|
||||||
|
contact.save
|
||||||
|
contact.statuses.should == [Contact::SERVER_UPDATE_PROHIBITED]
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should have linked status when domain' do
|
it 'should have linked status when domain' do
|
||||||
@tech_domain_contact = Fabricate(:tech_domain_contact, contact_id: @contact.id)
|
contact = Fabricate(:contact)
|
||||||
@domain = Fabricate(:domain, tech_domain_contacts: [@tech_domain_contact])
|
tech_domain_contact = Fabricate(:tech_domain_contact, contact_id: @contact.id)
|
||||||
contact = @domain.contacts.first
|
contact.statuses.should == %w(ok)
|
||||||
contact.save
|
# domain = Fabricate(:domain, tech_domain_contacts: [@tech_domain_contact])
|
||||||
|
|
||||||
contact.statuses.map(&:value).sort.should == %w(linked ok)
|
contact.save
|
||||||
|
contact.reload.statuses.should == %w(linked ok)
|
||||||
|
|
||||||
|
# contact = @domain.contacts.first
|
||||||
|
# contact.save
|
||||||
|
|
||||||
|
# contact.statuses.sort.should == %w(linked ok)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should not have linked status when no domain' do
|
it 'should not have linked status when no domain' do
|
||||||
|
@ -173,11 +198,11 @@ describe Contact do
|
||||||
contact = @domain.contacts.first
|
contact = @domain.contacts.first
|
||||||
contact.save
|
contact.save
|
||||||
|
|
||||||
contact.statuses.map(&:value).sort.should == %w(linked ok)
|
contact.statuses.sort.should == %w(linked ok)
|
||||||
|
|
||||||
contact.domains.first.destroy
|
contact.domains.first.destroy
|
||||||
contact.reload
|
contact.reload
|
||||||
contact.statuses.map(&:value).should == %w(ok)
|
contact.statuses.should == %w(ok)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should have code' do
|
it 'should have code' do
|
||||||
|
@ -193,6 +218,15 @@ describe Contact do
|
||||||
# contact.statuses.map(&:value).should == %w(ok linked)
|
# contact.statuses.map(&:value).should == %w(ok linked)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'should save status notes' do
|
||||||
|
contact = Fabricate(:contact)
|
||||||
|
contact.statuses = ['serverDeleteProhibited', 'serverUpdateProhibited']
|
||||||
|
contact.status_notes_array = [nil, 'update manually turned off']
|
||||||
|
contact.status_notes['serverDeleteProhibited'].should == nil
|
||||||
|
contact.status_notes['serverUpdateProhibited'].should == 'update manually turned off'
|
||||||
|
contact.status_notes['someotherstatus'].should == nil
|
||||||
|
end
|
||||||
|
|
||||||
context 'as birthday' do
|
context 'as birthday' do
|
||||||
before do
|
before do
|
||||||
@domain = Fabricate(:domain)
|
@domain = Fabricate(:domain)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue