diff --git a/app/controllers/admin/contacts_controller.rb b/app/controllers/admin/contacts_controller.rb index 23d743719..a8a062af8 100644 --- a/app/controllers/admin/contacts_controller.rb +++ b/app/controllers/admin/contacts_controller.rb @@ -11,9 +11,38 @@ class Admin::ContactsController < AdminController render json: Contact.search_by_query(params[:q]) 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 def set_contact @contact = Contact.includes(domains: :registrar).find(params[:id]) 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 diff --git a/app/models/contact.rb b/app/models/contact.rb index 4a33d6716..8f83eb805 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -5,10 +5,12 @@ class Contact < ActiveRecord::Base belongs_to :registrar has_many :domain_contacts has_many :domains, through: :domain_contacts - has_many :statuses, class_name: 'ContactStatus', dependent: :destroy has_many :legal_documents, as: :documentable 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 validates :name, :phone, :email, :ident, :ident_type, @@ -26,6 +28,12 @@ class Contact < ActiveRecord::Base format: { with: /\A[\w\-\:]*\Z/i, message: :invalid }, length: { maximum: 100, message: :too_long_contact_code } 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 :prefix_code @@ -37,10 +45,10 @@ class Contact < ActiveRecord::Base ContactMailer.email_updated(self).deliver_now end - after_save :manage_statuses + before_save :manage_statuses def manage_statuses - ContactStatus.manage(statuses, self) - statuses.reload + manage_linked + manage_ok end scope :current_registrars, ->(id) { where(registrar_id: id) } @@ -58,6 +66,79 @@ class Contact < ActiveRecord::Base 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 def search_by_query(query) res = search(code_cont: query).result @@ -83,6 +164,20 @@ class Contact < ActiveRecord::Base def privs where("ident_type = '#{PRIV}'") 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 def roid @@ -104,6 +199,12 @@ class Contact < ActiveRecord::Base end end + def uniq_statuses? + return true unless statuses.detect { |s| statuses.count(s) > 1 } + errors.add(:statuses, :not_uniq) + false + end + def bic? ident_type == BIC end @@ -206,4 +307,48 @@ class Contact < ActiveRecord::Base @desc 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 diff --git a/app/models/contact_status.rb b/app/models/contact_status.rb deleted file mode 100644 index 50eac9077..000000000 --- a/app/models/contact_status.rb +++ /dev/null @@ -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 diff --git a/app/models/depricated_contact_status.rb b/app/models/depricated_contact_status.rb new file mode 100644 index 000000000..b67722ac4 --- /dev/null +++ b/app/models/depricated_contact_status.rb @@ -0,0 +1,5 @@ +class DepricatedContactStatus < ActiveRecord::Base + self.table_name = :contact_statuses + self.sequence_name = :contact_statuses_id_seq + belongs_to :contact +end diff --git a/app/models/domain.rb b/app/models/domain.rb index 9a475f7f9..70eedccc8 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -54,9 +54,10 @@ class Domain < ActiveRecord::Base delegate :name, to: :registrar, prefix: true delegate :street, to: :registrar, prefix: true - after_initialize :init_default_values - def init_default_values + after_initialize do self.pending_json = {} if pending_json.blank? + self.statuses = [] if statuses.nil? + self.status_notes = {} if status_notes.nil? end before_create :generate_auth_info @@ -77,7 +78,6 @@ class Domain < ActiveRecord::Base end after_save :update_whois_record - after_initialize -> { self.statuses = [] if statuses.nil? } after_create :update_reserved_domains def update_reserved_domains diff --git a/app/models/epp/domain.rb b/app/models/epp/domain.rb index 382a59029..bb03da524 100644 --- a/app/models/epp/domain.rb +++ b/app/models/epp/domain.rb @@ -484,7 +484,7 @@ class Epp::Domain < Domain def copy_and_transfer_contact(contact_id, registrar_id) c = Contact.find(contact_id) # n+1 workaround - oc = c.deep_clone include: [:statuses] + oc = c.deep_clone oc.code = nil oc.registrar_id = registrar_id oc.prefix_code diff --git a/app/views/admin/contacts/_form.haml b/app/views/admin/contacts/_form.haml new file mode 100644 index 000000000..acb4c30df --- /dev/null +++ b/app/views/admin/contacts/_form.haml @@ -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') diff --git a/app/views/admin/contacts/edit.haml b/app/views/admin/contacts/edit.haml new file mode 100644 index 000000000..62498ec3f --- /dev/null +++ b/app/views/admin/contacts/edit.haml @@ -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 diff --git a/app/views/admin/contacts/form_partials/_statuses.haml b/app/views/admin/contacts/form_partials/_statuses.haml new file mode 100644 index 000000000..3b913bdd9 --- /dev/null +++ b/app/views/admin/contacts/form_partials/_statuses.haml @@ -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() diff --git a/app/views/admin/contacts/partials/_general.haml b/app/views/admin/contacts/partials/_general.haml index dc1c277fb..066b70ae5 100644 --- a/app/views/admin/contacts/partials/_general.haml +++ b/app/views/admin/contacts/partials/_general.haml @@ -12,7 +12,6 @@ %br - %dt= t(:ident) %dd= ident_for(@contact) diff --git a/app/views/admin/contacts/partials/_statuses.haml b/app/views/admin/contacts/partials/_statuses.haml index b0e1f7b86..c39075754 100644 --- a/app/views/admin/contacts/partials/_statuses.haml +++ b/app/views/admin/contacts/partials/_statuses.haml @@ -7,12 +7,12 @@ %thead %tr %th{class: 'col-xs-6'}= t(:status) - %th{class: 'col-xs-6'}= t(:description) + %th{class: 'col-xs-6'}= t(:notes) %tbody - - contact.statuses.each do |s| + - contact.statuses.each do |status| %tr - %td= s.value - %td= s.description + %td= status + %td= contact.status_notes[status] - if contact.errors.messages[:statuses] %tfoot diff --git a/app/views/admin/contacts/show.haml b/app/views/admin/contacts/show.haml index 5b266bdd9..affc55cd7 100644 --- a/app/views/admin/contacts/show.haml +++ b/app/views/admin/contacts/show.haml @@ -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 .row diff --git a/app/views/admin/domains/_form.haml b/app/views/admin/domains/_form.haml index 3e16d5f03..570b8397b 100644 --- a/app/views/admin/domains/_form.haml +++ b/app/views/admin/domains/_form.haml @@ -10,7 +10,3 @@ .row .col-md-8.text-right = button_tag(t(:save), class: 'btn btn-primary') - -:coffee - $ -> - $("#tabs a:first").tab "show" diff --git a/app/views/epp/contacts/info.xml.builder b/app/views/epp/contacts/info.xml.builder index da8edbdf7..30afc4196 100644 --- a/app/views/epp/contacts/info.xml.builder +++ b/app/views/epp/contacts/info.xml.builder @@ -10,7 +10,7 @@ xml.epp_head do xml.tag!('contact:roid', @contact.roid) @contact.statuses.each do |status| - xml.tag!('contact:status', s: status.value) + xml.tag!('contact:status', s: status) end xml.tag!('contact:postalInfo', type: 'int') do diff --git a/app/views/shared/_errors.haml b/app/views/shared/_errors.haml index bcbdd7121..1f3e177d0 100644 --- a/app/views/shared/_errors.haml +++ b/app/views/shared/_errors.haml @@ -2,5 +2,5 @@ - object.errors.each do |attr, err| - next if attr.match(/\./) - next if attr == :epp_errors - = err + = "#{attr.to_s.humanize} #{err}" %br diff --git a/config/environments/test.rb b/config/environments/test.rb index b56e173c1..ee1ae12b7 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -44,7 +44,7 @@ Rails.application.configure do # The available log levels are: :debug, :info, :warn, :error, :fatal, and :unknown, # corresponding to the log level numbers from 0 up to 5 respectively - config.log_level = :fatal + config.log_level = :info # for finding database optimization config.after_initialize do diff --git a/config/locales/en.yml b/config/locales/en.yml index 7a85dbbcf..c4b70c2e9 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -52,6 +52,8 @@ en: invalid_country_code: "Ident country code is not valid, should be in ISO_3166-1 alpha 2 format" domains: exist: 'Object association prohibits operation' + statuses: + not_uniq: 'not uniq' epp_domain: &epp_domain_ar_attributes attributes: @@ -874,3 +876,4 @@ en: domain_registrant_updated: 'Domeeni %{name} registreerija vahetus teostatud / Registrant change of %{name} has been finished.' api_user_not_found: 'API user not found' domain_already_belongs_to_the_querying_registrar: 'Domain already belongs to the querying registrar' + notes: Notes diff --git a/db/data/20150707103801_refactor_contact_statuses.rb b/db/data/20150707103801_refactor_contact_statuses.rb new file mode 100644 index 000000000..be6312016 --- /dev/null +++ b/db/data/20150707103801_refactor_contact_statuses.rb @@ -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 diff --git a/db/migrate/20150707103241_add_statuses_to_contact.rb b/db/migrate/20150707103241_add_statuses_to_contact.rb new file mode 100644 index 000000000..466043f62 --- /dev/null +++ b/db/migrate/20150707103241_add_statuses_to_contact.rb @@ -0,0 +1,5 @@ +class AddStatusesToContact < ActiveRecord::Migration + def change + add_column :contacts, :statuses, :string, array: true + end +end diff --git a/db/migrate/20150722071128_add_contact_and_domain_status_notes.rb b/db/migrate/20150722071128_add_contact_and_domain_status_notes.rb new file mode 100644 index 000000000..908345c2c --- /dev/null +++ b/db/migrate/20150722071128_add_contact_and_domain_status_notes.rb @@ -0,0 +1,6 @@ +class AddContactAndDomainStatusNotes < ActiveRecord::Migration + def change + add_column :contacts, :status_notes, :hstore + add_column :domains, :status_notes, :hstore + end +end diff --git a/db/schema-read-only.rb b/db/schema-read-only.rb index 7880fe213..f7f535ed6 100644 --- a/db/schema-read-only.rb +++ b/db/schema-read-only.rb @@ -11,7 +11,7 @@ # # 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 enable_extension "plpgsql" @@ -200,6 +200,7 @@ ActiveRecord::Schema.define(version: 20150713113436) do t.string "state" t.integer "legacy_id" t.string "statuses", array: true + t.hstore "status_notes" end 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" 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| t.integer "domain_id" t.string "key_tag" @@ -327,6 +322,7 @@ ActiveRecord::Schema.define(version: 20150713113436) do t.datetime "force_delete_at" t.string "statuses", array: true t.boolean "reserved", default: false + t.hstore "status_notes" end add_index "domains", ["delete_at"], name: "index_domains_on_delete_at", using: :btree diff --git a/db/structure.sql b/db/structure.sql index f8e53da5d..46aaf34c1 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -632,7 +632,8 @@ CREATE TABLE contacts ( country_code character varying, state character varying, 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; --- --- 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: -- @@ -945,7 +937,8 @@ CREATE TABLE domains ( pending_json json, force_delete_at timestamp without time zone, 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); --- --- 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: -- @@ -4861,10 +4847,6 @@ INSERT INTO schema_migrations (version) VALUES ('20150522164020'); 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 ('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 ('20150609093515'); - 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 ('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 ('20150612125720'); - INSERT INTO schema_migrations (version) VALUES ('20150701074344'); 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 ('20150707103801'); - INSERT INTO schema_migrations (version) VALUES ('20150707104937'); 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 ('20150722071128'); + diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb index 4b99e9d0e..7c4bf3406 100644 --- a/spec/models/contact_spec.rb +++ b/spec/models/contact_spec.rb @@ -100,6 +100,12 @@ describe Contact do @contact.errors[:code].should == ['Contact code is too long, max 100 characters'] 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 @contact.related_domain_descriptions.should == {} end @@ -154,17 +160,36 @@ describe Contact do end it 'should have ok status by default' do - @contact.statuses.size.should == 1 - @contact.statuses.first.value.should == 'ok' + @contact.statuses.should == %w(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 it 'should have linked status when domain' do - @tech_domain_contact = Fabricate(:tech_domain_contact, contact_id: @contact.id) - @domain = Fabricate(:domain, tech_domain_contacts: [@tech_domain_contact]) - contact = @domain.contacts.first - contact.save + contact = Fabricate(:contact) + tech_domain_contact = Fabricate(:tech_domain_contact, contact_id: @contact.id) + contact.statuses.should == %w(ok) + # 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 it 'should not have linked status when no domain' do @@ -173,11 +198,11 @@ describe Contact do contact = @domain.contacts.first contact.save - contact.statuses.map(&:value).sort.should == %w(linked ok) + contact.statuses.sort.should == %w(linked ok) contact.domains.first.destroy contact.reload - contact.statuses.map(&:value).should == %w(ok) + contact.statuses.should == %w(ok) end it 'should have code' do @@ -193,6 +218,15 @@ describe Contact do # contact.statuses.map(&:value).should == %w(ok linked) 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 before do @domain = Fabricate(:domain)