diff --git a/app/controllers/admin/domain_contacts_controller.rb b/app/controllers/admin/domain_contacts_controller.rb new file mode 100644 index 000000000..1ce42f6aa --- /dev/null +++ b/app/controllers/admin/domain_contacts_controller.rb @@ -0,0 +1,48 @@ +class Admin::DomainContactsController < ApplicationController + before_action :set_domain + before_action :set_domain_contact, only: [:destroy] + + def new + @domain_contact = @domain.domain_contacts.build + end + + def create + @domain.adding_admin_contact = true + @domain_contact = @domain.domain_contacts.build(domain_contact_params) + + if @domain.save + flash[:notice] = I18n.t('shared.contact_added') + redirect_to [:admin, @domain] + else + flash.now[:alert] = I18n.t('shared.failed_to_add_contact') + render 'new' + end + end + + def destroy + @domain.deleting_admin_contact = true + @domain.domain_contacts.select { |x| x == @domain_contact }[0].mark_for_destruction + + if @domain.save + flash[:notice] = I18n.t('shared.contact_deleted') + else + flash[:alert] = I18n.t('shared.fail') + end + + redirect_to [:admin, @domain] + end + + private + + def set_domain + @domain = Domain.find(params[:domain_id]) + end + + def set_domain_contact + @domain_contact = DomainContact.find(params[:id]) + end + + def domain_contact_params + params.require(:domain_contact).permit(:contact_id, :contact_type) + end +end diff --git a/app/controllers/admin/domain_statuses_controller.rb b/app/controllers/admin/domain_statuses_controller.rb index 830608b8e..b3ddbfdaa 100644 --- a/app/controllers/admin/domain_statuses_controller.rb +++ b/app/controllers/admin/domain_statuses_controller.rb @@ -2,7 +2,6 @@ class Admin::DomainStatusesController < ApplicationController before_action :set_domain before_action :set_domain_status, only: [:edit, :update, :destroy] - def new @domain_status = @domain.domain_statuses.build(value: DomainStatus::OK) end diff --git a/app/controllers/admin/nameservers_controller.rb b/app/controllers/admin/nameservers_controller.rb index 3bd8f2880..5ff356aa3 100644 --- a/app/controllers/admin/nameservers_controller.rb +++ b/app/controllers/admin/nameservers_controller.rb @@ -7,13 +7,8 @@ class Admin::NameserversController < ApplicationController end def create - unless @domain.can_add_nameserver? - @nameserver = @domain.nameservers.build(nameserver_params) - flash.now[:alert] = I18n.t('shared.failed_to_add_nameserver') - render 'new' and return - end - - @domain.nameservers.build(nameserver_params) + @domain.adding_nameserver = true + @nameserver = @domain.nameservers.build(nameserver_params) if @domain.save flash[:notice] = I18n.t('shared.nameserver_added') @@ -29,7 +24,7 @@ class Admin::NameserversController < ApplicationController end def update - if @nameserver.update(nameserver_params) && @domain.valid? + if @nameserver.update(nameserver_params) redirect_to [:admin, @domain] else render 'edit' @@ -37,12 +32,11 @@ class Admin::NameserversController < ApplicationController end def destroy - if @domain.can_remove_nameserver? - if @nameserver.destroy - flash[:notice] = I18n.t('shared.nameserver_deleted') - else - flash[:alert] = I18n.t('shared.failed_to_delete_nameserver') - end + @domain.deleting_nameserver = true + @domain.nameservers.select { |x| x == @nameserver }[0].mark_for_destruction + + if @domain.save + flash[:notice] = I18n.t('shared.nameserver_deleted') else flash[:alert] = @domain.errors[:nameservers].first end diff --git a/app/models/domain.rb b/app/models/domain.rb index 87e038c1d..95bb29400 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -4,7 +4,9 @@ class Domain < ActiveRecord::Base belongs_to :registrar belongs_to :owner_contact, class_name: 'Contact' - has_many :domain_contacts, dependent: :delete_all + has_many :domain_contacts, dependent: :delete_all, autosave: true + + accepts_nested_attributes_for :domain_contacts, allow_destroy: true has_many :tech_contacts, -> do where(domain_contacts: { contact_type: DomainContact::TECH }) @@ -14,7 +16,7 @@ class Domain < ActiveRecord::Base where(domain_contacts: { contact_type: DomainContact::ADMIN }) end, through: :domain_contacts, source: :contact - has_many :nameservers, dependent: :delete_all + has_many :nameservers, dependent: :delete_all, autosave: true has_many :domain_statuses, dependent: :delete_all @@ -36,6 +38,18 @@ class Domain < ActiveRecord::Base validate :validate_period + attr_accessor :adding_admin_contact + validate :validate_admin_contacts_max_count, if: :adding_admin_contact + + attr_accessor :deleting_admin_contact + validate :validate_admin_contacts_min_count, if: :deleting_admin_contact + + attr_accessor :adding_nameserver + validate :validate_nameserver_max_count, if: :adding_nameserver + + attr_accessor :deleting_nameserver + validate :validate_nameserver_min_count, if: :deleting_nameserver + def name=(value) value.strip! write_attribute(:name, SimpleIDN.to_unicode(value)) @@ -48,20 +62,28 @@ class Domain < ActiveRecord::Base end ### VALIDATIONS ### - def can_remove_nameserver? - sg = SettingGroup.domain_validation - min = sg.setting(:ns_min_count).value.to_i - return true if nameservers.length > min - errors.add(:nameservers, :greater_than_or_equal_to, { count: min }) - false + def validate_admin_contacts_max_count + return if admin_contacts_count < 4 + errors.add(:admin_contacts, :out_of_range) end - def can_add_nameserver? + def validate_admin_contacts_min_count + return if admin_contacts_count > 2 + errors.add(:admin_contacts, :out_of_range) + end + + def validate_nameserver_max_count sg = SettingGroup.domain_validation max = sg.setting(:ns_max_count).value.to_i - return true if nameservers.length < max + return if nameservers.length <= max errors.add(:nameservers, :less_than_or_equal_to, { count: max }) - false + end + + def validate_nameserver_min_count + sg = SettingGroup.domain_validation + min = sg.setting(:ns_min_count).value.to_i + return if nameservers.reject(&:marked_for_destruction?).length >= min + errors.add(:nameservers, :greater_than_or_equal_to, { count: min }) end def can_remove_admin_contact? diff --git a/app/models/domain_contact.rb b/app/models/domain_contact.rb index 56f6e7c53..d0b0050d0 100644 --- a/app/models/domain_contact.rb +++ b/app/models/domain_contact.rb @@ -5,4 +5,7 @@ class DomainContact < ActiveRecord::Base TECH = 'tech' ADMIN = 'admin' TYPES = [TECH, ADMIN] + + scope :admin, -> { where(contact_type: ADMIN) } + scope :tech, -> { where(contact_type: TECH) } end diff --git a/app/views/admin/domain_contacts/new.haml b/app/views/admin/domain_contacts/new.haml new file mode 100644 index 000000000..e31f61a4c --- /dev/null +++ b/app/views/admin/domain_contacts/new.haml @@ -0,0 +1,25 @@ +.row + .col-sm-6 + %h2.text-center-xs + = "#{t('shared.new_domain_contact')}" + .col-sm-6 + %h2.text-right.text-center-xs + = link_to(t('shared.back_to_domain'), [:admin, @domain], class: 'btn btn-default') +%hr += form_for([:admin, @domain, @domain_contact]) do |f| + .row + .col-md-6 + .form-group + = f.label :contact_type + = f.select :contact_type, options_for_select(DomainContact::TYPES, @domain_contact.contact_type), {}, {class: 'form-control'} + .col-md-6 + .form-group.has-feedback + = f.label :contact + = text_field_tag(:contact, params[:contact], class: 'form-control js-contact-typeahead', placeholder: t('shared.contact_code'), autocomplete: 'off') + %span.glyphicon.glyphicon-ok.form-control-feedback.js-typeahead-ok.hidden + %span.glyphicon.glyphicon-remove.form-control-feedback.js-typeahead-remove + = f.hidden_field(:contact_id, class: 'js-contact-id') + .row + .col-md-12.text-right + = button_tag(t('shared.save'), class: 'btn btn-primary') + diff --git a/app/views/admin/domains/partials/_admin_contacts.haml b/app/views/admin/domains/partials/_admin_contacts.haml index f8fda3b9c..6b7731902 100644 --- a/app/views/admin/domains/partials/_admin_contacts.haml +++ b/app/views/admin/domains/partials/_admin_contacts.haml @@ -13,13 +13,13 @@ %th{class: 'col-xs-5'}= t('shared.email') %th{class: 'col-xs-3'}= t('shared.action') %tbody - - @domain.admin_contacts.each do |x| + - @domain.domain_contacts.admin.each do |x| %tr - %td= link_to(x, root_path) - %td= x.email + %td= link_to(x.contact, root_path) + %td= x.contact.email %td = link_to(t('shared.edit'), root_path, class: 'btn btn-primary btn-xs') - = link_to(t('shared.detach'), admin_domain_admin_contact_path(@domain, x), method: :delete, data: { confirm: t('shared.are_you_sure') }, class: 'btn btn-warning btn-xs') + = link_to(t('shared.detach'), admin_domain_domain_contact_path(@domain, x), method: :delete, data: { confirm: t('shared.are_you_sure') }, class: 'btn btn-warning btn-xs') - if @domain.errors.messages[:admin_contacts] %tfoot - @domain.errors.messages[:admin_contacts].each do |x| diff --git a/config/routes.rb b/config/routes.rb index 9d6d5892c..9656067cc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,6 +8,7 @@ Rails.application.routes.draw do namespace(:admin) do resources :domains do resources :nameservers + resources :domain_contacts resources :tech_contacts resources :admin_contacts resources :domain_statuses